Compare commits

...

374 Commits

Author SHA1 Message Date
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
Daniel Colascione
91299a279b Fix window resize on DPI change 2019-09-24 12:41:23 -07: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
Kovid Goyal
d218900b57 Remove unused header 2019-07-29 09:45:02 +05:30
Kovid Goyal
cab949a939 Fix building with compilers that dont support __has_include 2019-07-29 09:44:05 +05:30
Kovid Goyal
e350822f5e version 0.14.3 2019-07-29 09:29:50 +05:30
Kovid Goyal
3d6fe93297 DRYer 2019-07-29 09:23:29 +05:30
Kovid Goyal
3a5baf2722 Merge branch 'doc/mapping_shortcuts' of https://github.com/MagicDuck/kitty 2019-07-29 09:13:16 +05:30
Stephan Badragan
cdb472cb56 Adding documentation for how to map shortcuts 2019-07-28 15:53:44 -07:00
Kovid Goyal
e634350e77 Merge branch 'indentation' of https://github.com/Luflosi/kitty 2019-07-28 10:55:49 +05:30
Luflosi
464a6c1441 Fix indentation of bool variables in glfw/egl_context.h
Caused by fe62700825.
2019-07-28 00:23:17 -05:00
Kovid Goyal
d3750b2244 Merge branch 'glfw_reduce_difference' of https://github.com/Luflosi/kitty 2019-07-28 10:48:22 +05:30
Luflosi
b8d2b76ee4 Reduce the difference of glfw to upstream 2019-07-28 00:10:50 -05:00
Kovid Goyal
14fb7c3201 Merge branch 'glfw_fix_invalid_gamepad_axis_ranges' of https://github.com/Luflosi/kitty 2019-07-27 08:20:02 +05:30
Luflosi
922bc62e0e GLFW: Fix invalid ranges for gamepad axis sources
From 9420e6f0d0.
2019-07-26 13:30:38 -05:00
Kovid Goyal
00cae4ccd1 Merge branch 'indentation' of https://github.com/Luflosi/kitty 2019-07-26 23:00:25 +05:30
Luflosi
61df266df7 Fix indentation of bool variables in glfw/internal.h
Caused by fe62700825.
2019-07-26 11:45:32 -05:00
Kovid Goyal
17751666f2 Merge branch 'glfw_documentation_work' of https://github.com/Luflosi/kitty 2019-07-26 12:04:32 +05:30
Luflosi
961b2c9b65 GLFW: Documentation work
From 3cf7645b96.
2019-07-25 23:07:00 -05:00
Kovid Goyal
eaf6f06047 Merge branch 'remove_empty_line' of https://github.com/Luflosi/kitty 2019-07-26 08:27:57 +05:30
Luflosi
d0ac218c05 Remove empty line 2019-07-25 20:41:08 -05:00
Kovid Goyal
1a01bc15d8 Merge branch 'more_modern_objective-c' of https://github.com/Luflosi/kitty 2019-07-26 06:06:58 +05:30
Luflosi
cdbe2f13ca Cocoa: Move slightly towards modern Objective-C
Inspired by 9a9568212c.
2019-07-25 17:14:32 -05:00
Kovid Goyal
4f5264277e Merge branch 'remove_space' of https://github.com/Luflosi/kitty 2019-07-25 22:12:28 +05:30
Luflosi
bed3adcc95 Remove space from cast in kitty/cocoa_window.m
All the other casts to `NSWindow` in this file have the same formatting.
2019-07-25 11:01:16 -05:00
Kovid Goyal
0c5d59bcf6 Merge branch 'move_dict_iter_define' of https://github.com/Luflosi/kitty 2019-07-25 10:13:58 +05:30
Luflosi
ff20acd8b8 Move #define dict_iter() closer to where it is used 2019-07-24 23:30:40 -05:00
Kovid Goyal
d1cffcde68 Merge branch 'one_less_monotonic' of https://github.com/Luflosi/kitty 2019-07-25 09:45:39 +05:30
Luflosi
546dd9b225 Remove unnecessary call to monotonic()
Assuming the call to `update_drag()` returns basically instantly, this call to `monotonic()` can be safely removed.
2019-07-24 23:12:50 -05:00
Kovid Goyal
2a666620c8 Merge branch 'autoreleasepool_comments' of https://github.com/Luflosi/kitty 2019-07-25 06:04:26 +05:30
Luflosi
db50985040 Format the @autoreleasepool blocks in kitty/cocoa_window.m like in GLFW 2019-07-24 18:03:40 -05:00
Kovid Goyal
8c6d593c41 Merge branch 'rename_cocoa_update_title' of https://github.com/Luflosi/kitty 2019-07-24 11:59:23 +05:30
Luflosi
40086c8d1c Rename cocoa_update_title() -> cocoa_update_menu_bar_title()
I renamed `cocoa_update_title()` to `cocoa_update_menu_bar_title()` since that more accurately reflects what this function actually does.
2019-07-23 15:06:18 -05:00
Kovid Goyal
38f73b9f5e Fix #1832 2019-07-23 13:31:09 +05:30
Kovid Goyal
49429b5f49 When zeroing memory, use type independent code
Reduces the potential for bugs
2019-07-23 10:54:10 +05:30
Kovid Goyal
d9f90ef077 Make qsort invocations type independent 2019-07-23 10:20:41 +05:30
Kovid Goyal
6a126fa18e Fix a crash when displaying very large number of images
Fixes #1825
2019-07-23 10:18:09 +05:30
Kovid Goyal
14d703f5cc Cleanup 2019-07-23 09:44:58 +05:30
Kovid Goyal
9850025f3a Use image ids instead of pointers when removing images since pointer values are changed by the remove operation 2019-07-23 09:40:41 +05:30
Kovid Goyal
8daab0ba41 Change image internal_id type to id_type 2019-07-23 09:34:04 +05:30
Kovid Goyal
88f25ccc76 Also handle non-absolute paths being used for $EDITOR 2019-07-22 10:30:11 +05:30
Kovid Goyal
50e7351c73 When detecting the EDITOR from the environment, if the EDITOR env var is not present, try to read it from the shell's rc files by executing a login shell and dumping its environment
macOS makes it unreasonably hard to set system-wide environment
variables, so this hack might be useful there.
2019-07-22 09:29:55 +05:30
Kovid Goyal
51453a54e4 Merge branch 'remove_wgl_context' of https://github.com/Luflosi/kitty 2019-07-22 06:31:32 +05:30
Luflosi
c02ba03f39 Remove glfw/wgl_context.c and glfw/wgl_context.h 2019-07-21 15:03:39 -05:00
Kovid Goyal
78dec3d698 Merge branch 'fix_assertion' of https://github.com/Luflosi/kitty 2019-07-21 09:54:15 +05:30
Luflosi
1590c59131 Fix assertion for glfwSetGamma value
From 751c6f9a27.
2019-07-20 23:17:58 -05:00
Kovid Goyal
b26f79998a Merge branch 'glfw_c_dialect_reminders' of https://github.com/Luflosi/kitty 2019-07-21 08:33:19 +05:30
Luflosi
489f3e6c9d Add C dialect reminders to each glfw source file
Reduces the difference to upstream.
From 56aad76b16.
2019-07-20 21:07:27 -05:00
Kovid Goyal
5fef4726a7 Cocoa: Fix file-local function not declared static
From upstream: 062a1c22b5
2019-07-20 19:12:21 +05:30
Kovid Goyal
51fdb8200a X11: Fix focus events not being filtered
From upstream: c6b95e3b07
2019-07-20 19:11:00 +05:30
Kovid Goyal
fb0d98ead1 Add more debugs to Wayland handleEvents() 2019-07-20 14:48:28 +05:30
Kovid Goyal
4096caba64 Cancel read if dispatch_pending fails 2019-07-20 14:32:57 +05:30
Kovid Goyal
38f77144fa Wayland: dont abort the event handler early if there are no pending events from the compositor. This ensures that the tick callback and other event sources are dispatched. 2019-07-20 14:09:09 +05:30
Kovid Goyal
b8041ce17f Wayland: Fix infinite loop if the compositor dies 2019-07-20 13:55:38 +05:30
Kovid Goyal
00575733c8 Merge branch 'current_move_events_modifiers' of https://github.com/Luflosi/kitty 2019-07-20 11:33:12 +05:30
Luflosi
621c92780c Get more up-to-date modifiers for mouse move events 2019-07-20 01:00:02 -05:00
Kovid Goyal
37f03af4b7 Merge branch 'glfw_copyright_years' of https://github.com/Luflosi/kitty 2019-07-20 11:14:11 +05:30
Luflosi
bdc4558a43 Update GLFW copyright years
Reduces the difference to upstream.
From ab118b2529.
2019-07-20 00:30:13 -05:00
Kovid Goyal
46d483e8b2 Merge branch 'add_kakoune_editor' of https://github.com/Luflosi/kitty 2019-07-20 08:53:35 +05:30
Luflosi
5143b62a07 Add kakoune to the list of editors 2019-07-20 01:07:10 +02:00
Kovid Goyal
87ed774cb4 Add a new option :opt:pointer_shape_when_grabbed that allows you to control the mouse pointer shape when the terminal programs grabs the pointer
Fixes #1808
2019-07-19 19:34:32 +05:30
Kovid Goyal
4e427d05b7 Fix mouse move events not having modifiers
The lack of modifiers meant that detect of whether the event should be
tracked in kitty was not working
2019-07-19 19:02:09 +05:30
Kovid Goyal
195d987331 Make handle_in_kitty consistent between the button and motion handlers 2019-07-19 18:58:46 +05:30
Kovid Goyal
9b58317fb1 Better fix for kitty not getting key events when launched via a symlink on macOS
Avoids the overhead of checking for a symlink and re-execing.
Apparently all that was needed was setting the correct activation
policy, glfw is supposed to do this but does it only if the menubar hint
is on, which we turn off as we create our own menubar.
2019-07-18 16:00:16 +05:30
Kovid Goyal
1cb15dedac Simplify the event loop code
Also reduce input latency by ignoring repaint_delay when
there is actual pending input.

Gets rid of request_tick_callback(). Now empty events
result in the tick callback being called so there is only a
single mechanism for waking up the main loop and getting
the tick callback called.
2019-07-18 15:51:54 +05:30
Kovid Goyal
5521d6b623 Reset the sigprocmask and signal handlers when launching child processes. Fixes #1806 2019-07-18 09:26:31 +05:30
Kovid Goyal
f5cf6c1dcb Also make the loop flags volatile 2019-07-17 19:55:19 +05:30
Kovid Goyal
89307727e7 Use atomic variables for main loop flags 2019-07-17 19:45:52 +05:30
Kovid Goyal
c30c21b250 Dont sort on mtime
Files are built in order by size anyway and mtime sort makes link order
mtime dependent which breaks reproducible builds on openSUSE as they
modify mtimes randomnly. See #1804
2019-07-16 20:10:14 +05:30
Kovid Goyal
b6fb087d7e sub-sort by filename in find_c_files() 2019-07-16 16:46:48 +05:30
Kovid Goyal
97c2b7c1fe Fix #1804 2019-07-16 07:22:31 +05:30
Kovid Goyal
81506640c8 Run instructions for empty event test 2019-07-15 21:31:31 +05:30
Kovid Goyal
8244f7cd58 Linux: Only process global state when something interesting happens
This matches behavior on macOS. Had initially set the code to process
on every loop tick in an attmept to workaround the issue of the event
loop freezing on X11 until an X event is delivered. However, in light
of #1782 that workaround was incorrect anyway. Better to have similar
behavior across platforms. This also has the advantage of reducing CPU
consumption.

Also add a simple program to test event loop wakeups.
2019-07-15 21:30:00 +05:30
Kovid Goyal
63573d6e26 DRYer 2019-07-15 18:23:17 +05:30
Kovid Goyal
9368f7f670 When using :opt:strip_trailing_spaces do not remove empty lines
Fixes #1802
2019-07-15 17:17:40 +05:30
Kovid Goyal
b7a11035d5 Merge branch 'master' of https://github.com/sterpe/kitty 2019-07-15 09:44:20 +05:30
Steven Richard Terpe
2e1b5e2fa7 Update docs on kitty completion for bash v3.2, etc
See kovidgoyal/kitty#1520
2019-07-14 13:59:03 -07:00
Kovid Goyal
8e5cbafe63 Fix kitty @focus-tab not reporting errors
Fixes #1799
2019-07-14 10:08:44 +05:30
Kovid Goyal
eb006a6688 Indicate if set_active_tab() worked or not 2019-07-14 10:02:33 +05:30
Kovid Goyal
40b9049deb Move the kitty OpenGL API into its own compilation unit 2019-07-12 15:29:48 +05:30
Kovid Goyal
64ffca2d0a Merge branch 'reword_changelog_entry' of https://github.com/Luflosi/kitty 2019-07-12 04:48:04 +05:30
Luflosi
1f4b6d4e9a Update a changelog entry to be more descriptive
I think it is not clear what this entry actually means without the additional explanation.
2019-07-11 19:30:19 +02:00
Kovid Goyal
eb30ba7722 Cocoa: Fix code to shutdown display link for inactive monitors 2019-07-11 22:34:28 +05:30
Kovid Goyal
3e0f4d36bc DRYer 2019-07-11 21:48:45 +05:30
Kovid Goyal
1fb118edee Merge branch 'relative_path_compile' of https://github.com/Luflosi/kitty 2019-07-11 21:45:22 +05:30
Luflosi
ca39634880 Use relative paths when compiling 2019-07-11 16:51:50 +02:00
Kovid Goyal
f8418d68a6 Fully drain the wakeupfd 2019-07-09 18:49:46 +05:30
Kovid Goyal
c0000fb24e Should use an unsigned int for eventfd 2019-07-09 18:42:17 +05:30
Kovid Goyal
c169f7ae83 Retry writing to wakeupfd on EAGAIN as well 2019-07-09 18:40:51 +05:30
Kovid Goyal
7ab5244bf5 ssh kitten: Make argument parsing more like ssh
Fixes #1787
2019-07-09 17:48:43 +05:30
Kovid Goyal
7e36489034 Dont call detect joysticks if support for them has been disabled 2019-07-08 11:18:00 +05:30
Kovid Goyal
d259b12ae7 Micro-optimization: Avoid repeated calls to XQLength 2019-07-08 11:05:04 +05:30
Kovid Goyal
8f8138d9bd Have monotic() return numbers offset from init time 2019-07-08 10:30:06 +05:30
Kovid Goyal
a8668f5fbf Add a separate CI job for linux-package
Should catch issues like #1786 in the future
2019-07-08 07:44:01 +05:30
Kovid Goyal
e00e6bd1c2 Dont print "done" when doing nothing 2019-07-08 07:36:30 +05:30
Kovid Goyal
0fc6c47556 Merge branch 'glad2' of https://github.com/Dav1dde/kitty 2019-07-08 07:31:38 +05:30
Kovid Goyal
d530dccb96 Move docs generation into create_linux_bundle_gunk 2019-07-08 07:26:07 +05:30
Kovid Goyal
37bf0e81d2 Fix #1786 2019-07-08 06:46:16 +05:30
David Herberth
f872f955b0 Replace glad with glad2 2019-07-07 21:10:15 +02:00
Kovid Goyal
003cd0a203 Add a little more event loop debug output 2019-07-07 06:10:59 +05:30
Kovid Goyal
e7173f8145 Linux: Fix a regression in 0.14.0 that caused the event loop to tick continuously, wasting CPU even when idle
Fixes #1782
2019-07-07 05:57:18 +05:30
Kovid Goyal
93af102bec Clean link_commands.json 2019-07-07 04:52:24 +05:30
Kovid Goyal
67f23664c9 Generate Wayland protocol definitions in parallel as well 2019-07-05 20:57:56 +05:30
Kovid Goyal
39f6071c68 macOS: Fix a deadlock with CVDisplayLink
I had added an optimization to not pass messages to
main thread every time the CVDisplayLink timer fired, unless
a render frame for that monitor was actually requested.

However, this optimization is impossible to implement wihtout a deadlock
since CVDisplayLink has its own internal lock that it does not expose.

So I guess macOS users with multiple monitors will simply have to take
the performance hit of useless wakeups sixty times a second for every
extra monitor.

Fixes #1779
2019-07-05 20:16:32 +05:30
Kovid Goyal
edc8878632 Use relative paths for object files 2019-07-05 19:13:34 +05:30
Kovid Goyal
93b62c4dfd Also redo linking if the link command changes 2019-07-05 19:09:10 +05:30
Kovid Goyal
c3e210c80f Less output when building 2019-07-05 18:34:01 +05:30
Kovid Goyal
9a5cc8f650 Mark source names with glfw backend prefix 2019-07-05 18:27:13 +05:30
Kovid Goyal
5e7fbfefe9 Refactor the compilation code
Makes it a bit more efficient. All compiling is done in parallel,
followed by all linking.
2019-07-05 18:13:21 +05:30
Kovid Goyal
29ad6fba22 Linux: Use eventfd rather than a pipe for loop wakeup 2019-07-05 14:54:54 +05:30
Kovid Goyal
c848c3ee0d Use an interrupt-safe close() 2019-07-05 14:39:07 +05:30
Kovid Goyal
547132131a Linux: use signalfd rather than a pipe to handle signals 2019-07-05 14:33:22 +05:30
Kovid Goyal
40186fb54b Restore accidentally removed signal.h include 2019-07-05 12:22:38 +05:30
Kovid Goyal
5dc4e79c8d Move code to handle loop wakeup and signals into its own module 2019-07-05 12:19:37 +05:30
Kovid Goyal
556992a117 Forgot to make the eventfd cloexec and non-blocking 2019-07-05 10:08:15 +05:30
Kovid Goyal
a41ef8d513 Abort if addWatch during initialization of poll data fails 2019-07-05 10:00:39 +05:30
Kovid Goyal
6d96a89328 Linux: Use the more efficient eventfd mechanism to wakeup the event loop 2019-07-05 09:54:24 +05:30
Kovid Goyal
0fb1481038 Move event loop wakeup code into backend_utils 2019-07-05 09:34:51 +05:30
Kovid Goyal
4b77530c65 Store a reference to the glfw window pointer in the NSWindow class as well 2019-07-04 09:56:59 +05:30
Kovid Goyal
cdb493cf50 Couple more MIN/MAX type fixes 2019-07-04 09:15:13 +05:30
Kovid Goyal
c9a574a764 Cocoa: Ensure no callbacks are called on the view even if it is retained after being released
Fixes #1761 (I hope)
2019-07-04 09:03:13 +05:30
Kovid Goyal
bdb633a882 Merge branch 'tabs_to_spaces' of https://github.com/Luflosi/kitty 2019-07-04 08:19:01 +05:30
Luflosi
37aee7133d Convert tabs to spaces 2019-07-03 20:28:40 +02:00
Kovid Goyal
2cfd55f3ce Linux: Use the system "bell" for the terminal bell
Adds libcanberra as a new dependency to play the system sound.
2019-07-03 22:06:47 +05:30
Kovid Goyal
2e8188e89d Add libcanberra to the CI linux image 2019-07-03 20:30:12 +05:30
Kovid Goyal
1e172caea3 - Add an option :opt:terminal_select_modifiers to control which modifiers are used to override mouse selection
Fixes #1774
2019-07-03 10:50:07 +05:30
Kovid Goyal
6866cd0fb8 Document shift selection override behavior 2019-07-03 10:46:16 +05:30
Kovid Goyal
2719926870 Add some documentation on how to get regexes in the hints kitten to match over multiple lines. 2019-07-03 10:45:37 +05:30
Kovid Goyal
406891abcc Merge branch 'move_so_tmp_location' of https://github.com/Luflosi/kitty 2019-07-02 07:04:12 +05:30
Luflosi
4be6e9009a Move temporary location for shared objects into build directory 2019-07-02 01:49:35 +02:00
Kovid Goyal
6a31909557 Make the MIN and MAX macros typesafe 2019-07-01 17:03:47 +05:30
Kovid Goyal
f49f0d19f9 oops 2019-07-01 16:39:02 +05:30
Kovid Goyal
a2407f94e4 Remove unnecessary call to monotonic() 2019-07-01 16:36:29 +05:30
Kovid Goyal
62a0be4a11 Fix #1771 2019-07-01 16:35:35 +05:30
Kovid Goyal
b9029f6c67 Remove unnecessary extra copy 2019-07-01 13:57:16 +05:30
Kovid Goyal
92496f42c9 Try a couple of different header files for the BTN_ includes 2019-07-01 10:48:35 +05:30
Kovid Goyal
841c907efc Build glfw with all warnings enabled 2019-07-01 10:42:07 +05:30
Kovid Goyal
9bc288cd8e ... 2019-07-01 08:49:18 +05:30
Kovid Goyal
2ef0391b08 Convert some declarations to C99 style
From upstream: 0c6b505619
2019-07-01 08:32:47 +05:30
Kovid Goyal
6db768d1a3 Remove unneeded header
Fixes #1768
2019-07-01 06:07:55 +05:30
Kovid Goyal
9b080950a9 Cocoa: Cleanup
This makes the Cocoa _glfwPlatformSetWindowMonitor consistent with its
X11 and Win32 counterparts.

From upstream: 3262c29440
2019-07-01 05:59:32 +05:30
Kovid Goyal
3cd1fef4cb X11: Clean up EWMH feature detection
From upstream: fad9896d38
2019-07-01 05:57:17 +05:30
Kovid Goyal
a491a801bf X11: Let the language initialize XEvent structs
From upstream: 1f508530f0
2019-07-01 05:47:04 +05:30
Kovid Goyal
41ebb72276 Merge branch 'clean_kitty_launcher' of https://github.com/Luflosi/kitty 2019-07-01 05:28:08 +05:30
Luflosi
e4c0e9073e Clean "kitty/launcher" 2019-07-01 01:15:33 +02:00
Kovid Goyal
efad733cc5 DRYer 2019-06-30 18:42:20 +05:30
Kovid Goyal
1fcd6e1811 macOS: Fix finding fallback font for private use unicode symbols not working reliably
Fixes #1650
2019-06-30 18:11:58 +05:30
Kovid Goyal
75d697fa97 Fix #1766 2019-06-30 16:07:45 +05:30
Kovid Goyal
cde69670ba Linux: Fix incorrect scaling for fallback fonts when the font has an underscore that renders out of bounds
The calc_cell_height() function should not use underscore heights when
called in contexts other than cell metrics calculation.

Fixes #1713
2019-06-30 08:51:35 +05:30
Kovid Goyal
0be6c9cb97 Allow passing a `!neighbor` argument to the new_window mapping to open a new window next to the active window
Fixes #1746
2019-06-29 15:13:54 +05:30
Kovid Goyal
8c9d2d3ca2 macOS: Reduce energy consumption when idle by shutting down Apple's display link thread after 30 second of inactivity
Fixes #1763
2019-06-29 14:21:47 +05:30
Kovid Goyal
c84e73d8e6 Add some docs for how the completion system can be extended for a new shell 2019-06-29 07:56:24 +05:30
Kovid Goyal
3fb00f6c70 Re-request render frames if we dont hear back in a quarter of a second
Fixes #1748 (I hope)
2019-06-28 18:26:11 +05:30
Kovid Goyal
86305fdeb3 Use CVDisplayLinkIsRunning() rather than tracking started state since the OS can apparently shutdown the thread on its own in some scenarios 2019-06-28 17:46:59 +05:30
Kovid Goyal
710e146d22 Remove Makefile rule for logo building as the logo is now in git 2019-06-28 17:36:06 +05:30
Kovid Goyal
d5abc84bea Remote control: Add a command kitty @ scroll-window to scroll windows 2019-06-28 17:07:31 +05:30
Kovid Goyal
6f8214c15c Add the generated macOS icons to git
Removes the need for optipng/librsvg when building kitty.
2019-06-28 13:48:09 +05:30
Kovid Goyal
a56475e32f Dont use chdir() in logo/make.py 2019-06-28 13:44:42 +05:30
Kovid Goyal
9dadd91887 Build the kitty logo on CircleCI 2019-06-28 12:07:52 +05:30
Kovid Goyal
df5a73bb35 Dont change dirs when packaging 2019-06-28 12:00:12 +05:30
Kovid Goyal
a50bf59a2c macOS: Use a minimal bundle for the in-source kitty launcher
This should allow the Cocoa UI integration to work when running
kitty as kitty/launcher/kitty

Fixes #1756
2019-06-28 11:20:59 +05:30
Kovid Goyal
241354ae52 Move generation of Info.plist into its own function 2019-06-28 10:47:00 +05:30
Kovid Goyal
c863116011 Merge branch 'strip_once' of https://github.com/Luflosi/kitty 2019-06-27 05:18:04 +05:30
Luflosi
5cbd591a1e .strip() only once
`ans.append('KITTY_VCS_REV="{}"'.format(rev.strip()))` strips the
whitespace again later.
2019-06-26 19:48:58 +02:00
Kovid Goyal
6bb78c9499 Merge branch 'empty_lines' of https://github.com/Luflosi/kitty 2019-06-26 22:34:38 +05:30
Luflosi
893f406a99 Remove empty lines 2019-06-26 17:50:14 +02:00
Kovid Goyal
f722b898b0 Remove hard-coded restriction on drawing borders when only a single window is present
Instead this is controlled by the active layout. Fixes #1750
2019-06-26 19:35:49 +05:30
Kovid Goyal
18335b3eac Merge branch 'unify_compilation_database_access' of https://github.com/Luflosi/kitty 2019-06-26 19:30:30 +05:30
Luflosi
4708b592e2 Unify compilation_database access
`file` and `arguments` are accessed using the square bracket syntax, while `output` is accessed using `.get()`. This commit uses square brackets for all three. This will throw a `KeyError` if `compilation_database` does not have the key, which is the correct behaviour IMO.
2019-06-26 15:16:14 +02:00
Kovid Goyal
7598a2965c Merge branch 'sys_stat.h_macos_only' of https://github.com/Luflosi/kitty 2019-06-26 18:01:04 +05:30
Luflosi
1b59761a19 Only #include <sys/stat.h> on macOS
The `<sys/stat.h>` include in `launcher.c` is only used to check if the executable is a symlink on macOS. Therefore it is not needed on other platforms.
2019-06-26 14:05:35 +02:00
Kovid Goyal
7fd1053e0f Merge branch 'clean_more' of https://github.com/Luflosi/kitty 2019-06-26 08:18:45 +05:30
Luflosi
e178e7f6a5 Clean asan-launcher and kitty-profile 2019-06-25 20:22:23 +02:00
Kovid Goyal
d0bf21ab16 ... 2019-06-25 20:00:58 +05:30
Kovid Goyal
c826965833 Use libdir_name when bundle gunking on linux 2019-06-25 18:47:09 +05:30
Kovid Goyal
a76db39c19 Use a symlink for the in src launcher in a package 2019-06-25 18:37:11 +05:30
Kovid Goyal
323a538bdd Fix #1744 2019-06-25 18:16:00 +05:30
Kovid Goyal
2435feca3b oops 2019-06-25 08:26:19 +05:30
Kovid Goyal
29d059680c Merge branch 'fix_kitty.app_incremental_build' of https://github.com/Luflosi/kitty 2019-06-25 08:14:23 +05:30
Luflosi
aaaf7f9d8b Fix incremental compilation
The macOS specific `package()` code changes the directory. This didn't cause any problems before 9135387cfa since `compile_commands.json` was written to the filesystem before `package()` was called. This is not the case anymore, which results in `compile_commands.json` being written into the `kitty.app` bundle. I fixed the problem by using a context manager to change the direcctory back after `kitty.app` was created.
2019-06-25 02:55:13 +02:00
Kovid Goyal
bc90ce569a Build kitty.app on CI 2019-06-24 18:17:26 +05:30
Kovid Goyal
27f9f1756b Test doc building on macOS 2019-06-24 18:09:06 +05:30
Kovid Goyal
9135387cfa Get rid of the various different launchers
Now there is only one launcher. Which means it can be used to start
kitty with profiling and ASAN in the natural way. The recommended
way to run kitty from source is now:

./kitty/launcher/kitty

The launcher also automatically re-execs to resolve symlinks on macOS.
2019-06-24 17:21:30 +05:30
Kovid Goyal
af3504e05c Ensure that ensure_space() does not leave a NULL pointer 2019-06-24 16:00:45 +05:30
Kovid Goyal
9c9eac9d46 Merge branch 'delete_.dSYM' of https://github.com/Luflosi/kitty 2019-06-24 15:59:30 +05:30
Luflosi
f28383206a Delete *.dSYM directories when cleaning 2019-06-24 10:48:33 +02:00
Kovid Goyal
ba1c093d18 Merge branch 'manual_cleaning' of https://github.com/Luflosi/kitty 2019-06-24 08:36:52 +05:30
Luflosi
3ea3a85694 Never delete any files in the .git directory when cleaning manually
This is how results can be removed from os.walk(), according to https://docs.python.org/3/library/os.html#os.walk.
2019-06-23 21:08:46 +02:00
Luflosi
0e1a423889 Always clean files manually instead of using git
I see a couple problems with using git to determine the files to delete:
- git needs to be installed
- The manual cleaning code is supposed to function correctly, so why not always use it? That way bugs in the manual cleaning code are also more likely to get discovered
- If some files ignored by git should not be deleted, they need to be added to a sort of blacklist. If some files should be deleted by the manual cleanup code, they need to be added to a sort of whitelist. If someone forgets to add files to one of these lists, then not deleting files that should be deleted is better than deleting files that should not be deleted.
2019-06-23 21:08:16 +02:00
Kovid Goyal
3ce68ed53f Merge branch 'dSYM' of https://github.com/Luflosi/kitty 2019-06-23 20:03:07 +05:30
Luflosi
90c10da398 Ignore all *.dSYM directories
Building `kitty-profile` on macOS creates a `kitty-profile.dSYM` directory, that should be ignored, just like `asan-launcher.dSYM`.
2019-06-23 14:18:45 +02:00
Kovid Goyal
630bf28c22 Add examples for how to use OSC codes to change colors 2019-06-23 08:05:19 +05:30
Kovid Goyal
ff89c1d8e4 oops 2019-06-23 07:36:21 +05:30
Kovid Goyal
96703c23c8 Deal with .git being a file when getting the VCS commit hash during building 2019-06-23 07:36:03 +05:30
Kovid Goyal
2b78f5adad Merge branch 'copy_and_paste_error' of https://github.com/Luflosi/kitty 2019-06-23 07:27:22 +05:30
Luflosi
ab7df777eb Fix copy & paste error 2019-06-22 17:52:26 +02:00
Kovid Goyal
adbc694ff8 Merge branch 'non-mutable_default_argument' of https://github.com/Luflosi/kitty 2019-06-22 20:45:12 +05:30
Luflosi
7709cdb12b Make default argument non-mutable
Calling `Env()` without the `ldpaths` parameter after a call with the `ldpaths` parameter, keeps the list from the first call because the argument is mutable. This is probably not what was intended. This commit fixes this issue and also reverts a change to two lines introduced in 091e74d618, which was probably a workaround for this issue.
2019-06-22 16:57:38 +02:00
Kovid Goyal
f6051f73f5 Use SPECIAL_SOURCES for KITTY_VCS_REV
Fixes #1734
2019-06-22 18:54:58 +05:30
Kovid Goyal
d5c2a21cdf Merge branch 'diff_glfw_upstream' of https://github.com/Luflosi/kitty 2019-06-21 19:52:53 +05:30
Luflosi
8ffc841a3a Reduce the difference of glfw/cocoa_* to upstream
This only changes some formatting, whitespace, etc.. There are no
changes to the functionality.
Let me know if you don't like some of those changes.
2019-06-21 15:53:26 +02:00
Kovid Goyal
6c478977bb Merge branch 'missing_space' of https://github.com/Luflosi/kitty 2019-06-21 15:58:59 +05:30
Luflosi
07beb53b37 Add space after "if" 2019-06-21 12:12:13 +02:00
Kovid Goyal
59df1a8647 Merge branch 'diff_glfw_upstream' of https://github.com/Luflosi/kitty 2019-06-21 08:25:34 +05:30
Luflosi
fb98aa650d Reduce the difference of glfw to upstream
This only changes some formatting, whitespace, etc.. There are no
changes to the functionality.
Let me know if you don't like some of those changes.
2019-06-20 21:40:59 +02:00
Kovid Goyal
9981b5a9c6 Update xcode version in macos brew CI build 2019-06-20 06:28:49 +05:30
Kovid Goyal
603533e632 Fix a regression that caused closing an overlay window to focus the previously focused window rather than the underlying window
Fixes #1720
2019-06-17 09:00:47 +05:30
Kovid Goyal
38bc90f724 unicode_input kitten: Fix a regression that broke using indices to select recently used symbols. 2019-06-17 07:11:07 +05:30
Kovid Goyal
721beb9202 More docs for the cell fragment shader 2019-06-14 11:11:43 +05:30
Kovid Goyal
2e99259589 Make it possible to run custom kittens via kitty +kitten
Should help reduce confusion about how kittens work. Fixes #1712
2019-06-14 09:05:03 +05:30
Kovid Goyal
83e6b75872 More helpful error message if user tries to run a custom kitten via kitty +kitten 2019-06-14 08:23:25 +05:30
Kovid Goyal
cf70946f50 ... 2019-06-13 05:08:13 +05:30
Luflosi
f1c36aba83 Reduce the difference of glfw/null_* to upstream
This only changes some formatting, whitespace, etc.. There are no
changes to the functionality.
Let me know if you don't like some of those changes.
2019-06-12 20:45:21 +02:00
Kovid Goyal
2973cf15a4 Dont leak a file descriptor if pthread_create() fails 2019-06-12 21:51:32 +05:30
Kovid Goyal
55969bc3c5 Also set cwd when piping to none 2019-06-12 21:43:13 +05:30
Kovid Goyal
a8504c971a Also set special env for piped child with no input 2019-06-12 21:36:13 +05:30
Kovid Goyal
1644de2083 Use an explicit pipe instead of relying on subprocess.PIPE
Not sure what the lifetime semantics for fds created by subprocess.PIPE
are
2019-06-12 21:31:06 +05:30
Kovid Goyal
dd1fb85f60 When piping data to a child in the pipe command do it in a thread so as not to block the UI
See #1708
2019-06-12 21:03:18 +05:30
Kovid Goyal
b945b19865 Make thread_write() more robust 2019-06-12 20:58:47 +05:30
Kovid Goyal
91bf9f2ec8 Ensure fd is blocking in thread_write() 2019-06-12 20:42:17 +05:30
Kovid Goyal
f151f4c165 Detach the stdin write thread so that it is auto-cleaned up 2019-06-12 20:36:53 +05:30
Kovid Goyal
95b9b2d373 Merge branch 'diff_glfw_upstream' of https://github.com/Luflosi/kitty 2019-06-12 19:40:07 +05:30
Luflosi
8be698681c Reduce the difference of glfw/wl_* to upstream
This only changes some formatting, whitespace, etc.. There are no
changes to the functionality.
Let me know if you don't like some of those changes.
2019-06-12 14:55:56 +02:00
Kovid Goyal
da3e1a3730 Finish documenting commands 2019-06-12 15:30:26 +05:30
Kovid Goyal
29f637c19a Document a couple more commands 2019-06-12 15:14:15 +05:30
Kovid Goyal
3d01565ba7 Document more commands 2019-06-12 15:01:14 +05:30
Kovid Goyal
962291cc8e Document another command 2019-06-12 13:41:46 +05:30
Kovid Goyal
a662dace9c Document a couple more commands 2019-06-12 13:33:12 +05:30
Kovid Goyal
d34e0b325e Document a couple more commands 2019-06-12 13:20:54 +05:30
Kovid Goyal
4c242ec528 Document a couple more commands 2019-06-12 13:17:28 +05:30
Kovid Goyal
658be9405f Document the kitty remote control protocol
Fixes #1646
2019-06-12 13:12:53 +05:30
Kovid Goyal
15e8f6ad8a Another fix to the scissor for rendering the cell area
With a cyan background it becomes apparent that the width/height are one
pixel too small
2019-06-12 10:37:20 +05:30
Kovid Goyal
a5aca35f1c Simplify and document the operation of the cell fragment shader
Also get rid of the unneccessary double bg_alpha followed by divide by
alpha step when rendering interleaved and premult
2019-06-12 10:22:47 +05:30
Kovid Goyal
ae9df1ffac oops 2019-06-12 08:03:10 +05:30
Kovid Goyal
8bf2e098f5 Fix an out of bounds read causing a crash when selecting text with the mouse in the alternate screen mode
Fixes #1578
2019-06-12 07:52:37 +05:30
Kovid Goyal
7091d554b5 Merge branch 'diff_glfw_upstream' of https://github.com/Luflosi/kitty 2019-06-12 05:17:15 +05:30
Luflosi
bada795320 Reduce the difference of glfw/x11_* to glfw upstream
This only changes some formatting, whitespace, etc.. There are no
changes to the functionality.
Let me know if you don't like some of those changes.
2019-06-11 17:57:39 +02:00
Kovid Goyal
7d385849fb Merge branch 'simplify_code' of https://github.com/Luflosi/kitty 2019-06-11 19:42:59 +05:30
Luflosi
78775b7f6b Use "with suppress()" to suppress a python exception 2019-06-11 15:48:27 +02:00
Kovid Goyal
8d21a5b6b3 Fallback on ctypes' find_library to load libxkbcommon 2019-06-11 16:58:57 +05:30
Kovid Goyal
9da095ca50 Fix #1703 2019-06-11 16:54:55 +05:30
Kovid Goyal
0fafc07db0 Fix #1702 2019-06-11 15:30:50 +05:30
178 changed files with 49086 additions and 42735 deletions

View File

@@ -10,9 +10,15 @@ jobs:
- run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi - run: if grep -Inr '\s$' kitty kitty_tests kittens docs *.py *.asciidoc *.rst .gitattributes .gitignore; then echo Trailing whitespace found, aborting.; exit 1; fi
- run: python3 -m flake8 --count . - run: python3 -m flake8 --count .
- run: python3 setup.py build --debug --verbose - run: python3 setup.py build --debug --verbose
- run: python3 test.py - run: ./kitty/launcher/kitty +launch test.py
- run: make FAIL_WARN=-W man - run: make FAIL_WARN=-W man
- run: make FAIL_WARN=-W html - run: make FAIL_WARN=-W html
lin-package:
docker:
- image: kovidgoyal/kitty-test:latest
steps:
- checkout
- run: python3 setup.py linux-package --update-check-interval=0 - run: python3 setup.py linux-package --update-check-interval=0
lin-35: lin-35:
@@ -26,7 +32,7 @@ jobs:
steps: steps:
- checkout - checkout
- run: /opt/py3.5/bin/python3 setup.py build --debug --verbose --sanitize - run: /opt/py3.5/bin/python3 setup.py build --debug --verbose --sanitize
- run: ./asan-launcher test.py - run: ./kitty/launcher/kitty +launch test.py
lin-37: lin-37:
docker: docker:
@@ -38,7 +44,7 @@ jobs:
steps: steps:
- checkout - checkout
- run: /opt/py3.7/bin/python3 setup.py build --debug --verbose --sanitize - run: /opt/py3.7/bin/python3 setup.py build --debug --verbose --sanitize
- run: ./asan-launcher test.py - run: ./kitty/launcher/kitty +launch test.py
lin-bundle: lin-bundle:
docker: docker:
@@ -49,8 +55,9 @@ jobs:
- checkout - checkout
- run: echo "export LD_LIBRARY_PATH=$SW/lib" >> $BASH_ENV - run: echo "export LD_LIBRARY_PATH=$SW/lib" >> $BASH_ENV
- run: echo "export PKG_CONFIG_PATH=$SW/lib/pkgconfig" >> $BASH_ENV - run: echo "export PKG_CONFIG_PATH=$SW/lib/pkgconfig" >> $BASH_ENV
- run: echo "export PYTHONHOME=$SW" >> $BASH_ENV
- run: $SW/bin/python3 setup.py build --debug --verbose - run: $SW/bin/python3 setup.py build --debug --verbose
- run: $SW/bin/python3 test.py - run: ./kitty/launcher/kitty +launch test.py
mac-bundle: mac-bundle:
macos: macos:
@@ -65,21 +72,23 @@ jobs:
- run: curl https://download.calibre-ebook.com/travis/kitty/osx.tar.xz | tar xJ -C $SW - run: curl https://download.calibre-ebook.com/travis/kitty/osx.tar.xz | tar xJ -C $SW
- run: echo "export PATH=$SW/bin:$PATH" >> $BASH_ENV - run: echo "export PATH=$SW/bin:$PATH" >> $BASH_ENV
- run: python3 setup.py build --debug --verbose - run: python3 setup.py build --debug --verbose
- run: python3 test.py - run: ./kitty/launcher/kitty +launch test.py
mac-brew: mac-brew:
macos: macos:
xcode: "10.1.0" xcode: "10.2.0"
environment: environment:
LC_ALL: en_US.UTF-8 LC_ALL: en_US.UTF-8
LANG: en_US.UTF-8 LANG: en_US.UTF-8
steps: steps:
- checkout - checkout
- run: brew bundle - run: brew bundle
- run: python3 logo/make.py
- run: python3 setup.py build --debug --verbose - run: python3 setup.py build --debug --verbose
- run: python3 test.py - run: ./kitty/launcher/kitty +launch test.py
- run: python3 setup.py macos-bundle - run: echo "export PATH=/usr/local/opt/sphinx-doc/bin:$PATH" >> $BASH_ENV
- run: python3 setup.py linux-package --verbose
- run: python3 setup.py kitty.app --verbose
- run: kitty.app/Contents/MacOS/kitty +runpy "from kitty.constants import *; print(kitty_exe())"
workflows: workflows:
@@ -90,5 +99,6 @@ workflows:
- lin-sys - lin-sys
- lin-35 - lin-35
- lin-37 - lin-37
- lin-package
- lin-bundle - lin-bundle
- mac-brew - mac-brew

View File

@@ -31,7 +31,7 @@ ENV LANG=en_US.UTF-8
RUN apt-get install -y libreadline-dev zlib1g-dev libssl-dev libbz2-dev libsqlite3-dev libffi-dev RUN apt-get install -y libreadline-dev zlib1g-dev libssl-dev libbz2-dev libsqlite3-dev libffi-dev
# kitty deps # kitty deps
RUN apt-get install -y libgl1-mesa-dev libxi-dev libxrandr-dev libxinerama-dev libxcursor-dev libxcb-xkb-dev libdbus-1-dev libxkbcommon-dev libharfbuzz-dev libpng-dev libfontconfig-dev libpython3-dev libxkbcommon-x11-dev python3-pygments RUN apt-get install -y libgl1-mesa-dev libxi-dev libxrandr-dev libxinerama-dev libxcursor-dev libxcb-xkb-dev libdbus-1-dev libxkbcommon-dev libharfbuzz-dev libpng-dev libfontconfig-dev libpython3-dev libxkbcommon-x11-dev python3-pygments libcanberra-dev
# Needed to build kitty docs # Needed to build kitty docs
RUN pip3 install sphinx RUN pip3 install sphinx

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

28
.gitignore vendored
View File

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

View File

@@ -1,6 +1,5 @@
brew 'pkg-config' brew 'pkg-config'
brew 'imagemagick' brew 'imagemagick'
brew 'optipng'
brew 'librsvg'
brew 'harfbuzz' brew 'harfbuzz'
brew 'python' brew 'python'
brew 'sphinx-doc'

View File

@@ -1,8 +1,8 @@
ifdef V ifdef V
VVAL=--verbose VVAL=--verbose
endif endif
ifdef VERBOSE ifdef VERBOSE
VVAL=--verbose VVAL=--verbose
endif endif
all: all:
@@ -28,12 +28,7 @@ asan:
profile: profile:
python3 setup.py build $(VVAL) --profile python3 setup.py build $(VVAL) --profile
logo/kitty.iconset/icon_256x256.png: logo/kitty.svg logo/make.py app:
logo/make.py
rendered_logo: logo/kitty.iconset/icon_256x256.png
app: rendered_logo
python3 setup.py kitty.app $(VVAL) python3 setup.py kitty.app $(VVAL)
man: man:

View File

@@ -1,19 +0,0 @@
/*
* asan-launcher.c
* Copyright (C) 2017 Kovid Goyal <kovid at kovidgoyal.net>
*
* Distributed under terms of the GPL3 license.
*/
#include <Python.h>
#define MAX_ARGC 1024
int main(int argc, char *argv[]) {
wchar_t *argvw[MAX_ARGC + 1] = {0};
argvw[0] = L"kitty";
for (int i = 1; i < argc; i++) argvw[i] = Py_DecodeLocale(argv[i], NULL);
int ret = Py_Main(argc, argvw);
for (int i = 1; i < argc; i++) PyMem_RawFree(argvw[i]);
return ret;
}

View File

@@ -20,6 +20,7 @@ Run-time dependencies:
* libpng * libpng
* freetype (not needed on macOS) * freetype (not needed on macOS)
* fontconfig (not needed on macOS) * fontconfig (not needed on macOS)
* libcanberra (not needed on macOS)
* ImageMagick (optional, needed to use the ``kitty icat`` tool to display images in the terminal) * ImageMagick (optional, needed to use the ``kitty icat`` tool to display images in the terminal)
* pygments (optional, need for syntax highlighting in ``kitty +kitten diff``) * pygments (optional, need for syntax highlighting in ``kitty +kitten diff``)
@@ -28,7 +29,7 @@ Build-time dependencies:
* gcc or clang * gcc or clang
* pkg-config * pkg-config
* For building on Linux in addition to the above dependencies you might also need to install the ``-dev`` packages for: * 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`` and ``libpython-dev``. ``libdbus-1-dev``, ``libxcursor-dev``, ``libxrandr-dev``, ``libxi-dev``, ``libxinerama-dev``, ``libgl1-mesa-dev``, ``libxkbcommon-x11-dev``, ``libfontconfig-dev``, ``libcanberra-dev`` and ``libpython-dev``.
if they are not already installed by your distro. if they are not already installed by your distro.
Install and run from source Install and run from source
@@ -44,25 +45,17 @@ Now build the native code parts of |kitty| with the following command::
You can run |kitty|, as:: You can run |kitty|, as::
python3 . ./kitty/launcher/kitty
If that works, you can create a script to launch |kitty|: If that works, you can create a symlink to the launcher in :file:`~/bin` or
some other directory on your PATH so that you can run |kitty| using
.. code-block:: sh
#!/usr/bin/env python3
import runpy
runpy.run_path('/path/to/kitty/dir', run_name='__main__')
And place it in :file:`~/bin` or :file:`/usr/bin` so that you can run |kitty| using
just ``kitty``. just ``kitty``.
Building kitty.app on macOS from source Building kitty.app on macOS from source
------------------------------------------- -------------------------------------------
Install `imagemagick`, `optipng` and `librsvg` using `brew` or similar (needed Run::
for the logo generation step). And run::
make app make app

View File

@@ -4,6 +4,133 @@ Changelog
|kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator. |kitty| is a feature full, cross-platform, *fast*, GPU based terminal emulator.
To update |kitty|, :doc:`follow the instructions <binary>`. To update |kitty|, :doc:`follow the instructions <binary>`.
0.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]
---------------------
- Remote control: Add a command `kitty @ scroll-window` to scroll windows
- Allow passing a ``!neighbor`` argument to the new_window mapping to open a
new window next to the active window (:iss:`1746`)
- Document the kitty remote control protocol (:iss:`1646`)
- Add a new option :opt:`pointer_shape_when_grabbed` that allows you to control
the mouse pointer shape when the terminal programs grabs the pointer
(:iss:`1808`)
- Add an option :opt:`terminal_select_modifiers` to control which modifiers
are used to override mouse selection even when a terminal application has
grabbed the mouse (:iss:`1774`)
- When piping data to a child in the pipe command do it in a thread so as not
to block the UI (:iss:`1708`)
- unicode_input kitten: Fix a regression that broke using indices to select
recently used symbols.
- Fix a regression that caused closing an overlay window to focus
the previously focused window rather than the underlying window (:iss:`1720`)
- macOS: Reduce energy consumption when idle by shutting down Apple's display
link thread after 30 second of inactivity (:iss:`1763`)
- Linux: Fix incorrect scaling for fallback fonts when the font has an
underscore that renders out of bounds (:iss:`1713`)
- macOS: Fix finding fallback font for private use unicode symbols not working
reliably (:iss:`1650`)
- Fix an out of bounds read causing a crash when selecting text with the mouse
in the alternate screen mode (:iss:`1578`)
- Linux: Use the system "bell" sound for the terminal bell. Adds libcanberra
as a new dependency to play the system sound.
- macOS: Fix a rare deadlock causing kitty to hang (:iss:`1779`)
- Linux: Fix a regression in 0.14.0 that caused the event loop to tick
continuously, wasting CPU even when idle (:iss:`1782`)
- ssh kitten: Make argument parsing more like ssh (:iss:`1787`)
- When using :opt:`strip_trailing_spaces` do not remove empty lines
(:iss:`1802`)
- Fix a crash when displaying very large number of images (:iss:`1825`)
0.14.2 [2019-06-09] 0.14.2 [2019-06-09]
--------------------- ---------------------
@@ -137,7 +264,7 @@ To update |kitty|, :doc:`follow the instructions <binary>`.
- macOS: Fix :kbd:`cmd+period` key not working (:iss:`1318`) - 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`) show the current window title in the menu-bar (:iss:`1066`)
- macOS: Workaround for cocoa bug that could cause the mouse cursor to become - macOS: Workaround for cocoa bug that could cause the mouse cursor to become

View File

@@ -276,6 +276,48 @@ def write_cli_docs(all_kitten_names):
# }}} # }}}
def write_remote_control_protocol_docs(): # {{{
from kitty.cmds import cmap
field_pat = re.compile(r'\s*([a-zA-Z0-9_+]+)\s*:\s*(.+)')
def format_cmd(p, name, cmd):
p(name)
p('-' * 80)
lines = cmd.__doc__.strip().splitlines()
fields = []
for line in lines:
m = field_pat.match(line)
if m is None:
p(line)
else:
fields.append((m.group(1), m.group(2)))
if fields:
p('\nFields are:\n')
for (name, desc) in fields:
if '+' in name:
title = name.replace('+', ' (required)')
else:
title = name
defval = cmd.get_default(name.replace('-', '_'), cmd)
if defval is not cmd:
title = f'{title} (default: {defval})'
else:
title = f'{title} (optional)'
p(f':code:`{title}`')
p(' ', desc), p()
p(), p()
with open(f'generated/rc.rst', 'w') as f:
p = partial(print, file=f)
for name in sorted(cmap):
cmd = cmap[name]
if not cmd.__doc__:
continue
name = name.replace('_', '-')
format_cmd(p, name, cmd)
# }}}
# config file docs {{{ # config file docs {{{
class ConfLexer(RegexLexer): class ConfLexer(RegexLexer):
@@ -483,9 +525,12 @@ def process_shortcut_link(env, refnode, has_explicit_title, title, target):
conf_name, slug = 'kitty', conf_name conf_name, slug = 'kitty', conf_name
full_name = conf_name + '.' + slug full_name = conf_name + '.' + slug
try: try:
target, title = shortcut_slugs[full_name] target, stitle = shortcut_slugs[full_name]
except KeyError: except KeyError:
logger.warning('Unknown shortcut: {}'.format(target), location=refnode) logger.warning('Unknown shortcut: {}'.format(target), location=refnode)
else:
if not has_explicit_title:
title = stitle
return title, target return title, target
@@ -537,6 +582,7 @@ def setup(app):
from kittens.runner import all_kitten_names from kittens.runner import all_kitten_names
all_kitten_names = all_kitten_names() all_kitten_names = all_kitten_names()
write_cli_docs(all_kitten_names) write_cli_docs(all_kitten_names)
write_remote_control_protocol_docs()
write_conf_docs(app, all_kitten_names) write_conf_docs(app, all_kitten_names)
app.add_lexer('session', SessionLexer()) app.add_lexer('session', SessionLexer())
app.add_role('link', link_role) app.add_role('link', link_role)

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 have ssh do this automatically, if possible, when connecting to a server, so that
all terminals work transparently. 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? Keys such as arrow keys, backspace, delete, home/end, etc. do not work when using su or sudo?
------------------------------------------------------------------------------------------------- -------------------------------------------------------------------------------------------------
@@ -103,6 +115,28 @@ for |kitty| and use :ref:`at_set-colors`.
A list of pre-made color themes for kitty is available at: A list of pre-made color themes for kitty is available at:
`kitty-themes <https://github.com/dexpota/kitty-themes>`_ `kitty-themes <https://github.com/dexpota/kitty-themes>`_
Examples of using OSC escape codes to set colors::
Change the default foreground color:
printf '\x1b]10;#ff0000\x1b\\'
Change the default background color:
printf '\x1b]11;blue\x1b\\'
Change the cursor color:
printf '\x1b]12;blue\x1b\\'
Change the selection background color:
printf '\x1b]17;blue\x1b\\'
Change the selection foreground color:
printf '\x1b]19;blue\x1b\\'
Change the nth color (0 - 255):
printf '\x1b]4;n;green\x1b\\'
You can use various syntaxes/names for color specifications in the above
examples. See `XParseColor <https://linux.die.net/man/3/xparsecolor>`_
for full details.
If a ``?`` is given rather than a color specification, kitty will respond
with the current value for the specified color.
How do I specify command line options for kitty on macOS? How do I specify command line options for kitty on macOS?
--------------------------------------------------------------- ---------------------------------------------------------------
@@ -130,7 +164,27 @@ only monospace fonts, since every cell in the grid has to be the same size. If
your font is not listed in ``kitty list-fonts`` it means that it is not your font is not listed in ``kitty list-fonts`` it means that it is not
monospace. On Linux you can list all monospace fonts with:: monospace. On Linux you can list all monospace fonts with::
fc-list : family spacing | grep 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>
Then, the font will be available in ``kitty list-fonts``.
How can I assign a single global shortcut to bring up the kitty terminal? How can I assign a single global shortcut to bring up the kitty terminal?
@@ -140,3 +194,31 @@ Bringing up applications on a single key press is the job of the window
manager/desktop environment. For ways to do it with kitty (or indeed any manager/desktop environment. For ways to do it with kitty (or indeed any
terminal) in different environments, terminal) in different environments,
see `here <https://github.com/kovidgoyal/kitty/issues/45>`_. see `here <https://github.com/kovidgoyal/kitty/issues/45>`_.
How do I map key presses in kitty to different keys in the terminal program?
--------------------------------------------------------------------------------------
This is accomplished by using ``map`` with :sc:`send_text <send_text>` in :file:`kitty.conf`.
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
the :sc:`send_text <send_text>` you can use the ``showkey`` utility. Run::
showkey -a
Then press the key you want to emulate. On macOS, this utility is currently not
available. The manual way to figure it out is:
1. Look up your key's decimal value in the table at the bottom of `this
page <http://ascii-table.com/ansi-escape-sequences.php>`_ or any
ANSI escape sequence table. There are different modifiers for :kbd:`ctrl`,
:kbd:`alt`, etc. For e.g., for :kbd:`ctrl+s`, find the ``S`` row and look at
the third column value, ``19``.
2. Convert the decimal value to hex with ``kitty +runpy "print(hex(19))"``.
This shows the hex value, ``13`` in this case.
3. Use ``\x(hexval)`` in your ``send_text`` command in kitty. So in this example, ``\x13``

View File

@@ -107,7 +107,8 @@ features of the graphics protocol:
sys.stdout.flush() sys.stdout.flush()
cmd.clear() 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 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 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 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 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 Detecting available transmission mediums

View File

@@ -368,6 +368,8 @@ Mouse features
columns. columns.
* Selecting text automatically copies it to the primary clipboard (on * Selecting text automatically copies it to the primary clipboard (on
platforms with a primary clipboard). platforms with a primary clipboard).
* You can select text with kitty even when a terminal program has grabbed
the mouse by holding down the :kbd:`shift` key.
Font control Font control
@@ -448,6 +450,14 @@ Add the following to your :file:`~/.bashrc`
source <(kitty + complete setup bash) source <(kitty + complete setup bash)
Older versions of bash (for example, v3.2) do not support
process substitution with the source command, in which
case you can try an alternative:
.. code-block:: sh
source /dev/stdin <<<"$(kitty + complete setup bash)"
zsh zsh
~~~~~~~~~ ~~~~~~~~~
@@ -486,3 +496,4 @@ See :doc:`changelog`.
* *
kittens/* kittens/*
generated/rc

View File

@@ -20,6 +20,10 @@ import tempfile
py3 = sys.version_info[0] > 2 py3 = sys.version_info[0] > 2
is64bit = platform.architecture()[0] == '64bit' is64bit = platform.architecture()[0] == '64bit'
is_macos = 'darwin' in sys.platform.lower() 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: try:
__file__ __file__
@@ -225,7 +229,8 @@ def script_launch():
def update_intaller_wrapper(): def update_intaller_wrapper():
# To run: python3 -c "import runpy; runpy.run_path('installer.py', run_name='update_wrapper')" installer.sh # 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] wrapper = sys.argv[-1]
with open(wrapper, 'r+b') as f: with open(wrapper, 'r+b') as f:
raw = f.read().decode('utf-8') raw = f.read().decode('utf-8')

View File

@@ -14,12 +14,12 @@ render loop to reduce CPU usage. See :ref:`conf-kitty-performance` for details.
See also the :opt:`sync_to_monitor` option to further decrease latency at the cost See also the :opt:`sync_to_monitor` option to further decrease latency at the cost
of some `tearing <https://en.wikipedia.org/wiki/Screen_tearing>`_ while scrolling. of some `tearing <https://en.wikipedia.org/wiki/Screen_tearing>`_ while scrolling.
You can generate detailed per-function performance data using You can generate detailed per-function performance data using `gperftools
`gperftools <https://github.com/gperftools/gperftools>`_. Build |kitty| with <https://github.com/gperftools/gperftools>`_. Build |kitty| with `make
`make profile` which will create an executable called `kitty-profile`. Run profile`. Run kitty and perform the task you want to analyse, for example,
that and perform the task you want to analyse, for example, scrolling a large scrolling a large file with `less`. After you quit, function call statistics
file with `less`. After you quit, function call statistics will be printed to will be printed to `stdout` and you can use tools like *kcachegrind* for more
`stdout` and you can use tools like *kcachegrind* for more detailed analysis. detailed analysis.
Here are some CPU usage numbers for the task of scrolling a file continuously Here are some CPU usage numbers for the task of scrolling a file continuously
in less. The CPU usage is for the terminal process and X together and is in less. The CPU usage is for the terminal process and X together and is

29
docs/rc_protocol.rst Normal file
View File

@@ -0,0 +1,29 @@
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 of kitty has the
form::
<ESC>P@kitty-cmd<JSON object><ESC>\
Where ``<ESC>`` is the byte ``0x1b``. The JSON object has the form::
{
'cmd': "command name",
'version': "kitty version",
'no_response': Optional Boolean,
'payload': <Optional JSON object>,
}
The ``version`` above is a string of the form :code:`0.14.2`. If you are developing a
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 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.
.. include:: generated/rc.rst

View File

@@ -134,5 +134,10 @@ still write to the pipes of any other program on the same computer and
therefore can control |kitty|. It can, however, be useful to block programs therefore can control |kitty|. It can, however, be useful to block programs
running on other computers (for example, over ssh) or as other users. running on other computers (for example, over ssh) or as other users.
Documentation for the remote control protocol
-----------------------------------------------
If you wish to develop your own client to talk to |kitty|, you
can use the :doc:`rc_protocol`.
.. include:: generated/cli-kitty-at.rst .. include:: generated/cli-kitty-at.rst

View File

@@ -29,10 +29,12 @@ def get_data(fname, folder='UCD'):
bn = os.path.basename(url) bn = os.path.basename(url)
local = os.path.join('/tmp', bn) local = os.path.join('/tmp', bn)
if os.path.exists(local): if os.path.exists(local):
data = open(local, 'rb').read() with open(local, 'rb') as f:
data = f.read()
else: else:
data = urlopen(url).read() 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(): for line in data.decode('utf-8').splitlines():
line = line.strip() line = line.strip()
if line and not line.startswith('#'): if line and not line.startswith('#'):
@@ -166,21 +168,20 @@ def write_case(spec, p):
@contextmanager @contextmanager
def create_header(path, include_data_types=True): def create_header(path, include_data_types=True):
f = open(path, 'w') with open(path, 'w') as f:
p = partial(print, file=f) p = partial(print, file=f)
p('// unicode data, built from the unicode standard on:', date.today()) p('// unicode data, built from the unicode standard on:', date.today())
p('// see gen-wcwidth.py') p('// see gen-wcwidth.py')
if path.endswith('.h'): if path.endswith('.h'):
p('#pragma once') p('#pragma once')
if include_data_types: if include_data_types:
p('#include "data-types.h"\n') p('#include "data-types.h"\n')
p('START_ALLOW_CASE_RANGE') p('START_ALLOW_CASE_RANGE')
p() p()
yield p yield p
p() p()
if include_data_types: if include_data_types:
p('END_ALLOW_CASE_RANGE') p('END_ALLOW_CASE_RANGE')
f.close()
def gen_emoji(): def gen_emoji():
@@ -282,7 +283,9 @@ def gen_ucd():
p('combining_type mark_for_codepoint(char_type c) {') p('combining_type mark_for_codepoint(char_type c) {')
rmap = codepoint_to_mark_map(p, mark_map) rmap = codepoint_to_mark_map(p, mark_map)
p('}\n') 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: 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( 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] rmap[0xfe0e], rmap[0xfe0f]

View File

@@ -8,9 +8,11 @@ import shlex
import shutil import shutil
import subprocess import subprocess
cmdline = ( cmdline = (
'glad --profile core --out-path {dest} --api gl=3.3 --generator {generator} --spec gl' 'glad --out-path {dest} --api gl:core=3.3 '
' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug' ' --extensions GL_ARB_texture_storage,GL_ARB_copy_image,GL_ARB_multisample,GL_ARB_robustness,GL_KHR_debug '
'c --header-only --debug'
) )
@@ -23,7 +25,7 @@ def regenerate():
clean('out') clean('out')
subprocess.check_call( subprocess.check_call(
shlex.split(cmdline.format(dest='out', generator='c-debug')) shlex.split(cmdline.format(dest='out'))
) )
@@ -32,33 +34,12 @@ def strip_trailing_whitespace(c):
def export(): def export():
c = open('out/src/glad.c', 'rb').read().decode('utf-8') with open('out/include/glad/gl.h', 'r', encoding='utf-8') as source:
functions = [] data = source.read()
data = strip_trailing_whitespace(data)
def sub(m): with open('../kitty/gl-wrapper.h', 'w', encoding='utf-8') as dest:
functions.append(m.group(2)) dest.write(data)
return m.group()
c = re.sub(r'^([A-Z0-9]+) glad_debug_([a-zA-Z0-9]+) = glad_debug_impl_\2;$', sub, c, flags=re.M)
switch = ['glad_debug_{0} = glad_{0}'.format(f) for f in functions]
c = c.replace('<glad/glad.h>', '"gl-wrapper.h"', 1)
c = '#pragma GCC diagnostic ignored "-Wpedantic"\n' + c
c += '''
int
init_glad(GLADloadproc load, int debug) {
int ret = gladLoadGLLoader(load);
if (ret && !debug) {
SUB;
}
return ret;
}'''.replace('SUB', ';\n '.join(switch), 1)
open('../kitty/gl-wrapper.c', 'w').write(strip_trailing_whitespace(c))
raw = open('out/include/glad/glad.h').read()
raw = raw.replace('<KHR/khrplatform.h>', '"khrplatform.h"')
raw += '\nint init_glad(GLADloadproc, int);\n'
open('../kitty/gl-wrapper.h', 'w').write(strip_trailing_whitespace(raw))
raw = open('out/include/KHR/khrplatform.h', 'rb').read().decode('utf-8')
open('../kitty/khrplatform.h', 'w').write(strip_trailing_whitespace(raw))
if __name__ == '__main__': if __name__ == '__main__':

89
glfw/backend_utils.c vendored
View File

@@ -11,6 +11,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h> #include <errno.h>
#include <float.h> #include <float.h>
#include <time.h> #include <time.h>
@@ -220,24 +222,90 @@ dispatchTimers(EventLoopData *eld) {
} }
static void static void
drain_wakeup_fd(int fd, int events, void* data) { drain_wakeup_fd(int fd, EventLoopData* eld) {
static char drain_buf[64]; static char drain_buf[64];
while(read(fd, drain_buf, sizeof(drain_buf)) < 0 && errno == EINTR); eld->wakeup_data_read = false;
while(true) {
ssize_t ret = read(fd, drain_buf, sizeof(drain_buf));
if (ret < 0) {
if (errno == EINTR) continue;
break;
}
if (ret > 0) { eld->wakeup_data_read = true; continue; }
break;
}
}
static void
mark_wakep_fd_ready(int fd UNUSED, int events UNUSED, void *data) {
((EventLoopData*)(data))->wakeup_fd_ready = true;
}
bool
initPollData(EventLoopData *eld, int display_fd) {
if (!addWatch(eld, "display", display_fd, POLLIN, 1, NULL, NULL)) return false;
#ifdef HAS_EVENT_FD
eld->wakeupFd = eventfd(0, EFD_CLOEXEC | EFD_NONBLOCK);
if (eld->wakeupFd == -1) return false;
const int wakeup_fd = eld->wakeupFd;
#else
if (pipe2(eld->wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0) return false;
const int wakeup_fd = eld->wakeupFds[0];
#endif
if (!addWatch(eld, "wakeup", wakeup_fd, POLLIN, 1, mark_wakep_fd_ready, eld)) return false;
return true;
} }
void void
initPollData(EventLoopData *eld, int wakeup_fd, int display_fd) { check_for_wakeup_events(EventLoopData *eld) {
addWatch(eld, "display", display_fd, POLLIN, 1, NULL, NULL); #ifdef HAS_EVENT_FD
addWatch(eld, "wakeup", wakeup_fd, POLLIN, 1, drain_wakeup_fd, NULL); int fd = eld->wakeupFd;
#else
int fd = eld->wakeupFds[0];
#endif
drain_wakeup_fd(fd, eld);
} }
void
wakeupEventLoop(EventLoopData *eld) {
#ifdef HAS_EVENT_FD
static const uint64_t value = 1;
while (write(eld->wakeupFd, &value, sizeof value) < 0 && (errno == EINTR || errno == EAGAIN));
#else
while (write(eld->wakeupFds[1], "w", 1) < 0 && (errno == EINTR || errno == EAGAIN));
#endif
}
#ifndef HAS_EVENT_FD
static inline void
closeFds(int *fds, size_t count) {
while(count--) {
if (*fds > 0) {
close(*fds);
*fds = -1;
}
fds++;
}
}
#endif
void
finalizePollData(EventLoopData *eld) {
#ifdef HAS_EVENT_FD
close(eld->wakeupFd); eld->wakeupFd = -1;
#else
closeFds(eld->wakeupFds, arraysz(eld->wakeupFds));
#endif
}
int int
pollForEvents(EventLoopData *eld, double timeout) { pollForEvents(EventLoopData *eld, double timeout) {
int read_ok = 0; int read_ok = 0;
timeout = prepareForPoll(eld, timeout); timeout = prepareForPoll(eld, timeout);
EVDBG("pollForEvents final timeout: %.3f", timeout);
int result; int result;
double end_time = monotonic() + timeout; double end_time = monotonic() + timeout;
eld->wakeup_fd_ready = false;
while(1) { while(1) {
if (timeout >= 0) { if (timeout >= 0) {
@@ -270,17 +338,6 @@ pollForEvents(EventLoopData *eld, double timeout) {
return read_ok; return read_ok;
} }
void
closeFds(int *fds, size_t count) {
while(count--) {
if (*fds > 0) {
close(*fds);
*fds = -1;
}
fds++;
}
}
// Splits and translates a text/uri-list into separate file paths // Splits and translates a text/uri-list into separate file paths
// NOTE: This function destroys the provided string // NOTE: This function destroys the provided string
// //

23
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> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@@ -29,6 +29,16 @@
#include <unistd.h> #include <unistd.h>
#include <stdbool.h> #include <stdbool.h>
#ifdef __has_include
#if __has_include(<sys/eventfd.h>)
#define HAS_EVENT_FD
#include <sys/eventfd.h>
#endif
#else
#define HAS_EVENT_FD
#include <sys/eventfd.h>
#endif
typedef unsigned long long id_type; typedef unsigned long long id_type;
typedef void(*watch_callback_func)(int, int, void*); typedef void(*watch_callback_func)(int, int, void*);
typedef void(*timer_callback_func)(id_type, void*); typedef void(*timer_callback_func)(id_type, void*);
@@ -56,13 +66,19 @@ typedef struct {
typedef struct { typedef struct {
struct pollfd fds[32]; struct pollfd fds[32];
#ifdef HAS_EVENT_FD
int wakeupFd;
#else
int wakeupFds[2]; int wakeupFds[2];
#endif
bool wakeup_data_read, wakeup_fd_ready;
nfds_t watches_count, timers_count; nfds_t watches_count, timers_count;
Watch watches[32]; Watch watches[32];
Timer timers[128]; Timer timers[128];
} EventLoopData; } EventLoopData;
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); 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 removeWatch(EventLoopData *eld, id_type watch_id);
void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled); void toggleWatch(EventLoopData *eld, id_type watch_id, int enabled);
@@ -75,6 +91,7 @@ double prepareForPoll(EventLoopData *eld, double timeout);
int pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout); int pollWithTimeout(struct pollfd *fds, nfds_t nfds, double timeout);
int pollForEvents(EventLoopData *eld, double timeout); int pollForEvents(EventLoopData *eld, double timeout);
unsigned dispatchTimers(EventLoopData *eld); unsigned dispatchTimers(EventLoopData *eld);
void closeFds(int *fds, size_t count); void finalizePollData(EventLoopData *eld);
void initPollData(EventLoopData *eld, int wakeup_fd, int display_fd); bool initPollData(EventLoopData *eld, int display_fd);
char** parseUriList(char* text, int* count); char** parseUriList(char* text, int* count);
void wakeupEventLoop(EventLoopData *eld);

View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 macOS - www.glfw.org // GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -23,9 +23,12 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
#include <sys/param.h> // For MAXPATHLEN #include <sys/param.h> // For MAXPATHLEN
#include <pthread.h>
// Change to our application bundle's resources directory, if present // Change to our application bundle's resources directory, if present
// //
@@ -247,13 +250,13 @@ static bool initializeTIS(void)
CFStringRef* kPropertyUnicodeKeyLayoutData = CFStringRef* kPropertyUnicodeKeyLayoutData =
CFBundleGetDataPointerForName(_glfw.ns.tis.bundle, CFBundleGetDataPointerForName(_glfw.ns.tis.bundle,
CFSTR("kTISPropertyUnicodeKeyLayoutData")); CFSTR("kTISPropertyUnicodeKeyLayoutData"));
_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource = *(void **)&_glfw.ns.tis.CopyCurrentKeyboardLayoutInputSource =
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle, CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
CFSTR("TISCopyCurrentKeyboardLayoutInputSource")); CFSTR("TISCopyCurrentKeyboardLayoutInputSource"));
_glfw.ns.tis.GetInputSourceProperty = *(void **)&_glfw.ns.tis.GetInputSourceProperty =
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle, CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
CFSTR("TISGetInputSourceProperty")); CFSTR("TISGetInputSourceProperty"));
_glfw.ns.tis.GetKbdType = *(void **)&_glfw.ns.tis.GetKbdType =
CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle, CFBundleGetFunctionPointerForName(_glfw.ns.tis.bundle,
CFSTR("LMGetKbdType")); CFSTR("LMGetKbdType"));
@@ -280,14 +283,16 @@ static bool initializeTIS(void)
- (void)selectedKeyboardInputSourceChanged:(NSObject* )object - (void)selectedKeyboardInputSourceChanged:(NSObject* )object
{ {
(void)object;
updateUnicodeDataNS(); updateUnicodeDataNS();
} }
- (void)doNothing:(id)object - (void)doNothing:(id)object
{ {
(void)object;
} }
@end // GLFWHelper @end // GLFWHelper
@interface GLFWApplication : NSApplication @interface GLFWApplication : NSApplication
- (void)tick_callback; - (void)tick_callback;
@@ -307,6 +312,7 @@ static bool initializeTIS(void)
} }
@end @end
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -332,6 +338,7 @@ is_cmd_period(NSEvent *event, NSEventModifierFlags modifierFlags) {
int _glfwPlatformInit(void) int _glfwPlatformInit(void)
{ {
@autoreleasepool { @autoreleasepool {
_glfw.ns.helper = [[GLFWHelper alloc] init]; _glfw.ns.helper = [[GLFWHelper alloc] init];
[NSThread detachNewThreadSelector:@selector(doNothing:) [NSThread detachNewThreadSelector:@selector(doNothing:)
@@ -374,6 +381,7 @@ int _glfwPlatformInit(void)
_glfw.ns.keyDownMonitor = _glfw.ns.keyDownMonitor =
[NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskKeyDown
handler:keydown_block]; handler:keydown_block];
if (_glfw.hints.init.ns.chdir) if (_glfw.hints.init.ns.chdir)
changeToResourcesDirectory(); changeToResourcesDirectory();
@@ -394,24 +402,20 @@ int _glfwPlatformInit(void)
if (!initializeTIS()) if (!initializeTIS())
return false; return false;
_glfw.ns.displayLinks.lock = [NSLock new];
_glfwInitTimerNS(); _glfwInitTimerNS();
_glfwInitJoysticksNS(); _glfwInitJoysticksNS();
_glfwPollMonitorsNS(); _glfwPollMonitorsNS();
}
return true; return true;
} // autoreleasepool
} }
void _glfwPlatformTerminate(void) void _glfwPlatformTerminate(void)
{ {
@autoreleasepool { @autoreleasepool {
if (_glfw.ns.displayLinks.lock) { _glfwClearDisplayLinks();
_glfwClearDisplayLinks();
[_glfw.ns.displayLinks.lock release];
_glfw.ns.displayLinks.lock = nil;
}
if (_glfw.ns.inputSource) if (_glfw.ns.inputSource)
{ {
@@ -444,6 +448,7 @@ void _glfwPlatformTerminate(void)
[_glfw.ns.helper release]; [_glfw.ns.helper release];
_glfw.ns.helper = nil; _glfw.ns.helper = nil;
} }
if (_glfw.ns.keyUpMonitor) if (_glfw.ns.keyUpMonitor)
[NSEvent removeMonitor:_glfw.ns.keyUpMonitor]; [NSEvent removeMonitor:_glfw.ns.keyUpMonitor];
if (_glfw.ns.keyDownMonitor) if (_glfw.ns.keyDownMonitor)
@@ -453,7 +458,8 @@ void _glfwPlatformTerminate(void)
_glfwTerminateNSGL(); _glfwTerminateNSGL();
_glfwTerminateJoysticksNS(); _glfwTerminateJoysticksNS();
}
} // autoreleasepool
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)
@@ -468,32 +474,56 @@ const char* _glfwPlatformGetVersionString(void)
static GLFWtickcallback tick_callback = NULL; static GLFWtickcallback tick_callback = NULL;
static void* tick_callback_data = NULL; static void* tick_callback_data = NULL;
static bool tick_callback_requested = false; static bool tick_callback_requested = false;
static pthread_t main_thread;
static NSLock *tick_lock = NULL;
void _glfwDispatchTickCallback() { void _glfwDispatchTickCallback() {
if (tick_callback) { if (tick_lock && tick_callback) {
tick_callback_requested = false; [tick_lock lock];
tick_callback(tick_callback_data); while(tick_callback_requested) {
tick_callback_requested = false;
tick_callback(tick_callback_data);
}
[tick_lock unlock];
} }
} }
void _glfwPlatformRequestTickCallback() { static void
request_tick_callback() {
if (!tick_callback_requested) { if (!tick_callback_requested) {
tick_callback_requested = true; tick_callback_requested = true;
[NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO]; [NSApp performSelectorOnMainThread:@selector(tick_callback) withObject:nil waitUntilDone:NO];
} }
} }
void _glfwPlatformPostEmptyEvent(void)
{
if (pthread_equal(pthread_self(), main_thread)) {
request_tick_callback();
} else if (tick_lock) {
[tick_lock lock];
request_tick_callback();
[tick_lock unlock];
}
}
void _glfwPlatformStopMainLoop(void) { void _glfwPlatformStopMainLoop(void) {
tick_callback = NULL;
[NSApp stop:nil]; [NSApp stop:nil];
_glfwPlatformPostEmptyEvent(); _glfwCocoaPostEmptyEvent();
} }
void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) { void _glfwPlatformRunMainLoop(GLFWtickcallback callback, void* data) {
main_thread = pthread_self();
tick_callback = callback; tick_callback = callback;
tick_callback_data = data; tick_callback_data = data;
tick_lock = [NSLock new];
[NSApp run]; [NSApp run];
[tick_lock release];
tick_lock = NULL;
tick_callback = NULL;
tick_callback_data = NULL;
} }

View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 Cocoa - www.glfw.org // GLFW 3.4 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages

View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 Cocoa - www.glfw.org // GLFW 3.4 Cocoa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net> // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -75,7 +77,7 @@ static long getElementValue(_GLFWjoystick* js, _GLFWjoyelementNS* element)
// //
static CFComparisonResult compareElements(const void* fp, static CFComparisonResult compareElements(const void* fp,
const void* sp, const void* sp,
void* user) void* user UNUSED)
{ {
const _GLFWjoyelementNS* fe = fp; const _GLFWjoyelementNS* fe = fp;
const _GLFWjoyelementNS* se = sp; const _GLFWjoyelementNS* se = sp;
@@ -117,9 +119,9 @@ static void closeJoystick(_GLFWjoystick* js)
// Callback for user-initiated joystick addition // Callback for user-initiated joystick addition
// //
static void matchCallback(void* context, static void matchCallback(void* context UNUSED,
IOReturn result, IOReturn result UNUSED,
void* sender, void* sender UNUSED,
IOHIDDeviceRef device) IOHIDDeviceRef device)
{ {
int jid; int jid;
@@ -270,9 +272,9 @@ static void matchCallback(void* context,
// Callback for user-initiated joystick removal // Callback for user-initiated joystick removal
// //
static void removeCallback(void* context, static void removeCallback(void* context UNUSED,
IOReturn result, IOReturn result UNUSED,
void* sender, void* sender UNUSED,
IOHIDDeviceRef device) IOHIDDeviceRef device)
{ {
int jid; int jid;
@@ -316,7 +318,7 @@ void _glfwInitJoysticksNS(void)
return; return;
} }
for (int i = 0; i < sizeof(usages) / sizeof(long); i++) for (size_t i = 0; i < sizeof(usages) / sizeof(long); i++)
{ {
const long page = kHIDPage_GenericDesktop; const long page = kHIDPage_GenericDesktop;

View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 macOS - www.glfw.org // GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -215,7 +217,7 @@ static void endFadeReservation(CGDisplayFadeReservationToken token)
// Finds and caches the NSScreen corresponding to the specified monitor // Finds and caches the NSScreen corresponding to the specified monitor
// //
bool refreshMonitorScreen(_GLFWmonitor* monitor) static bool refreshMonitorScreen(_GLFWmonitor* monitor)
{ {
if (monitor->ns.screen) if (monitor->ns.screen)
return true; return true;
@@ -243,49 +245,30 @@ bool refreshMonitorScreen(_GLFWmonitor* monitor)
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwClearDisplayLinks() { void _glfwClearDisplayLinks() {
[_glfw.ns.displayLinks.lock lock];
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
if (_glfw.ns.displayLinks.entries[i].displayLinkStarted) {
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
_glfw.ns.displayLinks.entries[i].displayLinkStarted = false;
}
if (_glfw.ns.displayLinks.entries[i].displayLink) { if (_glfw.ns.displayLinks.entries[i].displayLink) {
CVDisplayLinkStop(_glfw.ns.displayLinks.entries[i].displayLink);
CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink); CVDisplayLinkRelease(_glfw.ns.displayLinks.entries[i].displayLink);
_glfw.ns.displayLinks.entries[i].displayLink = nil; _glfw.ns.displayLinks.entries[i].displayLink = nil;
_glfw.ns.displayLinks.entries[i].lastRenderFrameRequestedAt = 0;
} }
} }
_glfw.ns.displayLinks.count = 0; _glfw.ns.displayLinks.count = 0;
[_glfw.ns.displayLinks.lock unlock];
} }
static CVReturn displayLinkCallback( static CVReturn displayLinkCallback(
CVDisplayLinkRef displayLink, CVDisplayLinkRef displayLink UNUSED,
const CVTimeStamp* now, const CVTimeStamp* outputTime, const CVTimeStamp* now UNUSED, const CVTimeStamp* outputTime UNUSED,
CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* userInfo) CVOptionFlags flagsIn UNUSED, CVOptionFlags* flagsOut UNUSED, void* userInfo)
{ {
CGDirectDisplayID displayID = (CGDirectDisplayID)userInfo; CGDirectDisplayID displayID = (CGDirectDisplayID)userInfo;
[_glfw.ns.displayLinks.lock lock]; NSNumber *arg = [NSNumber numberWithUnsignedInt:displayID];
bool notify = false; [NSApp performSelectorOnMainThread:@selector(render_frame_received:) withObject:arg waitUntilDone:NO];
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { [arg release];
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) {
if (_glfw.ns.displayLinks.entries[i].renderFrameRequested) {
notify = true;
_glfw.ns.displayLinks.entries[i].renderFrameRequested = false;
}
break;
}
}
[_glfw.ns.displayLinks.lock unlock];
if (notify) {
NSNumber *arg = [NSNumber numberWithUnsignedInt:displayID];
[NSApp performSelectorOnMainThread:@selector(render_frame_received:) withObject:arg waitUntilDone:NO];
[arg release];
}
return kCVReturnSuccess; return kCVReturnSuccess;
} }
static inline void createDisplayLink(CGDirectDisplayID displayID) { static inline void createDisplayLink(CGDirectDisplayID displayID) {
[_glfw.ns.displayLinks.lock lock];
if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return; if (_glfw.ns.displayLinks.count >= sizeof(_glfw.ns.displayLinks.entries)/sizeof(_glfw.ns.displayLinks.entries[0]) - 1) return;
for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) { for (size_t i = 0; i < _glfw.ns.displayLinks.count; i++) {
if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return; if (_glfw.ns.displayLinks.entries[i].displayID == displayID) return;
@@ -295,26 +278,24 @@ static inline void createDisplayLink(CGDirectDisplayID displayID) {
entry->displayID = displayID; entry->displayID = displayID;
CVDisplayLinkCreateWithCGDisplay(displayID, &entry->displayLink); CVDisplayLinkCreateWithCGDisplay(displayID, &entry->displayLink);
CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)displayID); CVDisplayLinkSetOutputCallback(entry->displayLink, &displayLinkCallback, (void*)(uintptr_t)displayID);
[_glfw.ns.displayLinks.lock unlock];
} }
// Poll for changes in the set of connected monitors // Poll for changes in the set of connected monitors
// //
void _glfwPollMonitorsNS(void) void _glfwPollMonitorsNS(void)
{ {
uint32_t i, j, displayCount, disconnectedCount; uint32_t displayCount;
CGDirectDisplayID* displays;
_GLFWmonitor** disconnected = NULL;
CGGetOnlineDisplayList(0, NULL, &displayCount); CGGetOnlineDisplayList(0, NULL, &displayCount);
displays = calloc(displayCount, sizeof(CGDirectDisplayID)); CGDirectDisplayID* displays = calloc(displayCount, sizeof(CGDirectDisplayID));
CGGetOnlineDisplayList(displayCount, displays, &displayCount); CGGetOnlineDisplayList(displayCount, displays, &displayCount);
_glfwClearDisplayLinks(); _glfwClearDisplayLinks();
for (i = 0; i < _glfw.monitorCount; i++) for (int i = 0; i < _glfw.monitorCount; i++)
_glfw.monitors[i]->ns.screen = nil; _glfw.monitors[i]->ns.screen = nil;
disconnectedCount = _glfw.monitorCount; _GLFWmonitor** disconnected = NULL;
uint32_t disconnectedCount = _glfw.monitorCount;
if (disconnectedCount) if (disconnectedCount)
{ {
disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*)); disconnected = calloc(_glfw.monitorCount, sizeof(_GLFWmonitor*));
@@ -323,19 +304,18 @@ void _glfwPollMonitorsNS(void)
_glfw.monitorCount * sizeof(_GLFWmonitor*)); _glfw.monitorCount * sizeof(_GLFWmonitor*));
} }
for (i = 0; i < displayCount; i++) for (uint32_t i = 0; i < displayCount; i++)
{ {
_GLFWmonitor* monitor;
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
if (CGDisplayIsAsleep(displays[i])) if (CGDisplayIsAsleep(displays[i]))
continue; continue;
for (j = 0; j < disconnectedCount; j++) // HACK: Compare unit numbers instead of display IDs to work around
// display replacement on machines with automatic graphics
// switching
const uint32_t unitNumber = CGDisplayUnitNumber(displays[i]);
for (uint32_t j = 0; j < disconnectedCount; j++)
{ {
// HACK: Compare unit numbers instead of display IDs to work around
// display replacement on machines with automatic graphics
// switching
if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber) if (disconnected[j] && disconnected[j]->ns.unitNumber == unitNumber)
{ {
disconnected[j] = NULL; disconnected[j] = NULL;
@@ -348,7 +328,7 @@ void _glfwPollMonitorsNS(void)
if (!name) if (!name)
name = _glfw_strdup("Unknown"); name = _glfw_strdup("Unknown");
monitor = _glfwAllocMonitor(name, size.width, size.height); _GLFWmonitor* monitor = _glfwAllocMonitor(name, size.width, size.height);
monitor->ns.displayID = displays[i]; monitor->ns.displayID = displays[i];
monitor->ns.unitNumber = unitNumber; monitor->ns.unitNumber = unitNumber;
createDisplayLink(monitor->ns.displayID); createDisplayLink(monitor->ns.displayID);
@@ -358,7 +338,7 @@ void _glfwPollMonitorsNS(void)
_glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST); _glfwInputMonitor(monitor, GLFW_CONNECTED, _GLFW_INSERT_LAST);
} }
for (i = 0; i < disconnectedCount; i++) for (uint32_t i = 0; i < disconnectedCount; i++)
{ {
if (disconnected[i]) if (disconnected[i])
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0); _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
@@ -373,24 +353,20 @@ void _glfwPollMonitorsNS(void)
// //
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired) void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{ {
CFArrayRef modes;
CFIndex count, i;
CVDisplayLinkRef link;
CGDisplayModeRef native = NULL;
GLFWvidmode current; GLFWvidmode current;
const GLFWvidmode* best; const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current); _glfwPlatformGetVideoMode(monitor, &current);
if (_glfwCompareVideoModes(&current, best) == 0) if (_glfwCompareVideoModes(&current, best) == 0)
return; return;
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
count = CFArrayGetCount(modes); const CFIndex count = CFArrayGetCount(modes);
CGDisplayModeRef native = NULL;
for (i = 0; i < count; i++) for (CFIndex i = 0; i < count; i++)
{ {
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
if (!modeIsGood(dm)) if (!modeIsGood(dm))
@@ -439,7 +415,7 @@ void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
{ {
} }
@@ -468,7 +444,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
*yscale = (float) (pixels.size.height / points.size.height); *yscale = (float) (pixels.size.height / points.size.height);
} }
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
int* xpos, int* ypos,
int* width, int* height)
{ {
if (!refreshMonitorScreen(monitor)) if (!refreshMonitorScreen(monitor))
return; return;
@@ -488,20 +466,16 @@ void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos
GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count) GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
{ {
CFArrayRef modes;
CFIndex found, i, j;
GLFWvidmode* result;
CVDisplayLinkRef link;
*count = 0; *count = 0;
CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL); CFArrayRef modes = CGDisplayCopyAllDisplayModes(monitor->ns.displayID, NULL);
found = CFArrayGetCount(modes); const CFIndex found = CFArrayGetCount(modes);
result = calloc(found, sizeof(GLFWvidmode)); GLFWvidmode* result = calloc(found, sizeof(GLFWvidmode));
for (i = 0; i < found; i++) for (CFIndex i = 0; i < found; i++)
{ {
CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); CGDisplayModeRef dm = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i);
if (!modeIsGood(dm)) if (!modeIsGood(dm))
@@ -509,7 +483,7 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link); const GLFWvidmode mode = vidmodeFromCGDisplayMode(dm, link);
for (j = 0; j < *count; j++) for (CFIndex j = 0; j < *count; j++)
{ {
if (_glfwCompareVideoModes(result + j, &mode) == 0) if (_glfwCompareVideoModes(result + j, &mode) == 0)
break; break;
@@ -530,21 +504,20 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode) void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode *mode)
{ {
CGDisplayModeRef displayMode;
CVDisplayLinkRef link; CVDisplayLinkRef link;
CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link); CVDisplayLinkCreateWithCGDisplay(monitor->ns.displayID, &link);
displayMode = CGDisplayCopyDisplayMode(monitor->ns.displayID); CGDisplayModeRef native = CGDisplayCopyDisplayMode(monitor->ns.displayID);
*mode = vidmodeFromCGDisplayMode(displayMode, link); *mode = vidmodeFromCGDisplayMode(native, link);
CGDisplayModeRelease(displayMode); CGDisplayModeRelease(native);
CVDisplayLinkRelease(link); CVDisplayLinkRelease(link);
} }
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
{ {
uint32_t i, size = CGDisplayGammaTableCapacity(monitor->ns.displayID); uint32_t size = CGDisplayGammaTableCapacity(monitor->ns.displayID);
CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue)); CGGammaValue* values = calloc(size * 3, sizeof(CGGammaValue));
CGGetDisplayTransferByTable(monitor->ns.displayID, CGGetDisplayTransferByTable(monitor->ns.displayID,
@@ -556,7 +529,7 @@ bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
_glfwAllocGammaArrays(ramp, size); _glfwAllocGammaArrays(ramp, size);
for (i = 0; i < size; i++) for (uint32_t i = 0; i < size; i++)
{ {
ramp->red[i] = (unsigned short) (values[i] * 65535); ramp->red[i] = (unsigned short) (values[i] * 65535);
ramp->green[i] = (unsigned short) (values[i + size] * 65535); ramp->green[i] = (unsigned short) (values[i + size] * 65535);
@@ -569,10 +542,9 @@ bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp)
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{ {
int i;
CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue)); CGGammaValue* values = calloc(ramp->size * 3, sizeof(CGGammaValue));
for (i = 0; i < ramp->size; i++) for (unsigned int i = 0; i < ramp->size; i++)
{ {
values[i] = ramp->red[i] / 65535.f; values[i] = ramp->red[i] / 65535.f;
values[i + ramp->size] = ramp->green[i] / 65535.f; values[i + ramp->size] = ramp->green[i] / 65535.f;

19
glfw/cocoa_platform.h vendored
View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 macOS - www.glfw.org // GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -116,8 +116,8 @@ typedef struct _GLFWwindowNS
id view; id view;
id layer; id layer;
bool maximized; bool maximized;
bool retina; bool retina;
// Cached window properties to filter out duplicate events // Cached window properties to filter out duplicate events
int width, height; int width, height;
@@ -144,8 +144,7 @@ typedef struct _GLFWDisplayLinkNS
{ {
CVDisplayLinkRef displayLink; CVDisplayLinkRef displayLink;
CGDirectDisplayID displayID; CGDirectDisplayID displayID;
bool displayLinkStarted; double lastRenderFrameRequestedAt;
bool renderFrameRequested;
} _GLFWDisplayLinkNS; } _GLFWDisplayLinkNS;
// Cocoa-specific global data // Cocoa-specific global data
@@ -154,7 +153,7 @@ typedef struct _GLFWlibraryNS
{ {
CGEventSourceRef eventSource; CGEventSourceRef eventSource;
id delegate; id delegate;
bool cursorHidden; bool cursorHidden;
TISInputSourceRef inputSource; TISInputSourceRef inputSource;
IOHIDManagerRef hidManager; IOHIDManagerRef hidManager;
id unicodeData; id unicodeData;
@@ -184,7 +183,6 @@ typedef struct _GLFWlibraryNS
struct { struct {
_GLFWDisplayLinkNS entries[256]; _GLFWDisplayLinkNS entries[256];
size_t count; size_t count;
id lock;
} displayLinks; } displayLinks;
} _GLFWlibraryNS; } _GLFWlibraryNS;
@@ -222,9 +220,12 @@ void _glfwInitTimerNS(void);
void _glfwPollMonitorsNS(void); void _glfwPollMonitorsNS(void);
void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwSetVideoModeNS(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor); void _glfwRestoreVideoModeNS(_GLFWmonitor* monitor);
float _glfwTransformYNS(float y); float _glfwTransformYNS(float y);
void _glfwClearDisplayLinks(void); void _glfwClearDisplayLinks(void);
void _glfwRestartDisplayLinks(void); void _glfwRestartDisplayLinks(void);
void _glfwCocoaPostEmptyEvent(short subtype, long data1, bool at_start);
void _glfwDispatchTickCallback(void); void _glfwDispatchTickCallback(void);
void _glfwDispatchRenderFrame(CGDirectDisplayID); void _glfwDispatchRenderFrame(CGDirectDisplayID);
void _glfwShutdownCVDisplayLink(unsigned long long, void*);
void _glfwCocoaPostEmptyEvent(void);

4
glfw/cocoa_time.c vendored
View File

@@ -1,5 +1,5 @@
//======================================================================== //========================================================================
// GLFW 3.3 macOS - www.glfw.org // GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org>
// //
@@ -23,6 +23,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"

File diff suppressed because it is too large Load Diff

4
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) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org>
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"

16
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> // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
// //
@@ -53,7 +53,7 @@ glfw_dbus_init(_GLFWDBUSData *dbus, EventLoopData *eld) {
} }
static void static void
on_dbus_watch_ready(int fd, int events, void *data) { on_dbus_watch_ready(int fd UNUSED, int events, void *data) {
DBusWatch *watch = (DBusWatch*)data; DBusWatch *watch = (DBusWatch*)data;
unsigned int flags = 0; unsigned int flags = 0;
if (events & POLLERR) flags |= DBUS_WATCH_ERROR; if (events & POLLERR) flags |= DBUS_WATCH_ERROR;
@@ -84,19 +84,19 @@ add_dbus_watch(DBusWatch *watch, void *data) {
} }
static void static void
remove_dbus_watch(DBusWatch *watch, void *data) { remove_dbus_watch(DBusWatch *watch, void *data UNUSED) {
id_type *idp = dbus_watch_get_data(watch); id_type *idp = dbus_watch_get_data(watch);
if (idp) removeWatch(dbus_data->eld, *idp); if (idp) removeWatch(dbus_data->eld, *idp);
} }
static void static void
toggle_dbus_watch(DBusWatch *watch, void *data) { toggle_dbus_watch(DBusWatch *watch, void *data UNUSED) {
id_type *idp = dbus_watch_get_data(watch); id_type *idp = dbus_watch_get_data(watch);
if (idp) toggleWatch(dbus_data->eld, *idp, dbus_watch_get_enabled(watch)); if (idp) toggleWatch(dbus_data->eld, *idp, dbus_watch_get_enabled(watch));
} }
static void static void
on_dbus_timer_ready(id_type timer_id, void *data) { on_dbus_timer_ready(id_type timer_id UNUSED, void *data) {
if (data) { if (data) {
DBusTimeout *t = (DBusTimeout*)data; DBusTimeout *t = (DBusTimeout*)data;
dbus_timeout_handle(t); dbus_timeout_handle(t);
@@ -123,13 +123,13 @@ add_dbus_timeout(DBusTimeout *timeout, void *data) {
} }
static void static void
remove_dbus_timeout(DBusTimeout *timeout, void *data) { remove_dbus_timeout(DBusTimeout *timeout, void *data UNUSED) {
id_type *idp = dbus_timeout_get_data(timeout); id_type *idp = dbus_timeout_get_data(timeout);
if (idp) removeTimer(dbus_data->eld, *idp); if (idp) removeTimer(dbus_data->eld, *idp);
} }
static void static void
toggle_dbus_timeout(DBusTimeout *timeout, void *data) { toggle_dbus_timeout(DBusTimeout *timeout, void *data UNUSED) {
id_type *idp = dbus_timeout_get_data(timeout); id_type *idp = dbus_timeout_get_data(timeout);
if (idp) toggleTimer(dbus_data->eld, *idp, dbus_timeout_get_enabled(timeout)); if (idp) toggleTimer(dbus_data->eld, *idp, dbus_timeout_get_enabled(timeout));
} }
@@ -178,7 +178,7 @@ glfw_dbus_session_bus_dispatch() {
} }
void void
glfw_dbus_terminate(_GLFWDBUSData *dbus) { glfw_dbus_terminate(_GLFWDBUSData *dbus UNUSED) {
if (dbus_data) { if (dbus_data) {
dbus_data->eld = NULL; dbus_data->eld = NULL;
dbus_data = NULL; dbus_data = NULL;

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> // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
// //

62
glfw/egl_context.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 EGL - www.glfw.org // GLFW 3.4 EGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@@ -253,8 +255,8 @@ static GLFWglproc getProcAddressEGL(const char* procname)
if (window->context.egl.client) if (window->context.egl.client)
{ {
GLFWglproc proc = (GLFWglproc) _glfw_dlsym(window->context.egl.client, GLFWglproc proc = NULL;
procname); glfw_dlsym(proc, window->context.egl.client, procname);
if (proc) if (proc)
return proc; return proc;
} }
@@ -335,38 +337,22 @@ bool _glfwInitEGL(void)
_glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0); _glfw.egl.prefix = (strncmp(sonames[i], "lib", 3) == 0);
_glfw.egl.GetConfigAttrib = (PFN_eglGetConfigAttrib) glfw_dlsym(_glfw.egl.GetConfigAttrib, _glfw.egl.handle, "eglGetConfigAttrib");
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigAttrib"); glfw_dlsym(_glfw.egl.GetConfigs, _glfw.egl.handle, "eglGetConfigs");
_glfw.egl.GetConfigs = (PFN_eglGetConfigs) glfw_dlsym(_glfw.egl.GetDisplay, _glfw.egl.handle, "eglGetDisplay");
_glfw_dlsym(_glfw.egl.handle, "eglGetConfigs"); glfw_dlsym(_glfw.egl.GetError, _glfw.egl.handle, "eglGetError");
_glfw.egl.GetDisplay = (PFN_eglGetDisplay) glfw_dlsym(_glfw.egl.Initialize, _glfw.egl.handle, "eglInitialize");
_glfw_dlsym(_glfw.egl.handle, "eglGetDisplay"); glfw_dlsym(_glfw.egl.Terminate, _glfw.egl.handle, "eglTerminate");
_glfw.egl.GetError = (PFN_eglGetError) glfw_dlsym(_glfw.egl.BindAPI, _glfw.egl.handle, "eglBindAPI");
_glfw_dlsym(_glfw.egl.handle, "eglGetError"); glfw_dlsym(_glfw.egl.CreateContext, _glfw.egl.handle, "eglCreateContext");
_glfw.egl.Initialize = (PFN_eglInitialize) glfw_dlsym(_glfw.egl.DestroySurface, _glfw.egl.handle, "eglDestroySurface");
_glfw_dlsym(_glfw.egl.handle, "eglInitialize"); glfw_dlsym(_glfw.egl.DestroyContext, _glfw.egl.handle, "eglDestroyContext");
_glfw.egl.Terminate = (PFN_eglTerminate) glfw_dlsym(_glfw.egl.CreateWindowSurface, _glfw.egl.handle, "eglCreateWindowSurface");
_glfw_dlsym(_glfw.egl.handle, "eglTerminate"); glfw_dlsym(_glfw.egl.MakeCurrent, _glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.BindAPI = (PFN_eglBindAPI) glfw_dlsym(_glfw.egl.SwapBuffers, _glfw.egl.handle, "eglSwapBuffers");
_glfw_dlsym(_glfw.egl.handle, "eglBindAPI"); glfw_dlsym(_glfw.egl.SwapInterval, _glfw.egl.handle, "eglSwapInterval");
_glfw.egl.CreateContext = (PFN_eglCreateContext) glfw_dlsym(_glfw.egl.QueryString, _glfw.egl.handle, "eglQueryString");
_glfw_dlsym(_glfw.egl.handle, "eglCreateContext"); glfw_dlsym(_glfw.egl.GetProcAddress, _glfw.egl.handle, "eglGetProcAddress");
_glfw.egl.DestroySurface = (PFN_eglDestroySurface)
_glfw_dlsym(_glfw.egl.handle, "eglDestroySurface");
_glfw.egl.DestroyContext = (PFN_eglDestroyContext)
_glfw_dlsym(_glfw.egl.handle, "eglDestroyContext");
_glfw.egl.CreateWindowSurface = (PFN_eglCreateWindowSurface)
_glfw_dlsym(_glfw.egl.handle, "eglCreateWindowSurface");
_glfw.egl.MakeCurrent = (PFN_eglMakeCurrent)
_glfw_dlsym(_glfw.egl.handle, "eglMakeCurrent");
_glfw.egl.SwapBuffers = (PFN_eglSwapBuffers)
_glfw_dlsym(_glfw.egl.handle, "eglSwapBuffers");
_glfw.egl.SwapInterval = (PFN_eglSwapInterval)
_glfw_dlsym(_glfw.egl.handle, "eglSwapInterval");
_glfw.egl.QueryString = (PFN_eglQueryString)
_glfw_dlsym(_glfw.egl.handle, "eglQueryString");
_glfw.egl.GetProcAddress = (PFN_eglGetProcAddress)
_glfw_dlsym(_glfw.egl.handle, "eglGetProcAddress");
if (!_glfw.egl.GetConfigAttrib || if (!_glfw.egl.GetConfigAttrib ||
!_glfw.egl.GetConfigs || !_glfw.egl.GetConfigs ||
@@ -446,7 +432,7 @@ void _glfwTerminateEGL(void)
#define setAttrib(a, v) \ #define setAttrib(a, v) \
{ \ { \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \ attribs[index++] = a; \
attribs[index++] = v; \ attribs[index++] = v; \
} }
@@ -714,7 +700,7 @@ bool _glfwCreateContextEGL(_GLFWwindow* window,
// Returns the Visual and depth of the chosen EGLConfig // Returns the Visual and depth of the chosen EGLConfig
// //
#if defined(_GLFW_X11) #if defined(_GLFW_X11)
bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig, bool _glfwChooseVisualEGL(const _GLFWwndconfig* wndconfig UNUSED,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth) Visual** visual, int* depth)

16
glfw/egl_context.h vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 EGL - www.glfw.org // GLFW 3.4 EGL - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -173,13 +173,13 @@ typedef struct _GLFWlibraryEGL
{ {
EGLDisplay display; EGLDisplay display;
EGLint major, minor; EGLint major, minor;
bool prefix; bool prefix;
bool KHR_create_context; bool KHR_create_context;
bool KHR_create_context_no_error; bool KHR_create_context_no_error;
bool KHR_gl_colorspace; bool KHR_gl_colorspace;
bool KHR_get_all_proc_addresses; bool KHR_get_all_proc_addresses;
bool KHR_context_flush_control; bool KHR_context_flush_control;
void* handle; void* handle;

View File

@@ -8,11 +8,7 @@ import re
import sys import sys
_plat = sys.platform.lower() _plat = sys.platform.lower()
is_macos = 'darwin' in _plat is_linux = 'linux' 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
base = os.path.dirname(os.path.abspath(__file__)) base = os.path.dirname(os.path.abspath(__file__))
@@ -23,35 +19,24 @@ def wayland_protocol_file_name(base, ext='c'):
def init_env(env, pkg_config, at_least_version, test_compile, module='x11'): def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
ans = env.copy() ans = env.copy()
ans.cflags = [
x for x in ans.cflags
if x not in '-Wpedantic -Wextra -pedantic-errors'.split()
]
if not is_macos:
ans.cflags.append('-pthread')
ans.ldpaths.append('-pthread')
ans.cflags.append('-fpic') ans.cflags.append('-fpic')
ans.cppflags.append('-D_GLFW_' + module.upper()) ans.cppflags.append('-D_GLFW_' + module.upper())
ans.cppflags.append('-D_GLFW_BUILD_DLL') ans.cppflags.append('-D_GLFW_BUILD_DLL')
if is_macos: with open(os.path.join(base, 'source-info.json')) as f:
ans.cppflags.append('-DGL_SILENCE_DEPRECATION') sinfo = json.load(f)
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')))
module_sources = list(sinfo[module]['sources']) module_sources = list(sinfo[module]['sources'])
if module in ('x11', 'wayland'): 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) module_sources.remove(remove)
ans.sources = sinfo['common']['sources'] + module_sources ans.sources = sinfo['common']['sources'] + module_sources
ans.all_headers = [x for x in os.listdir(base) if x.endswith('.h')] ans.all_headers = [x for x in os.listdir(base) if x.endswith('.h')]
if module in ('x11', 'wayland'): 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) at_least_version('xkbcommon', 0, 5)
if module == 'x11': if module == 'x11':
@@ -60,6 +45,7 @@ def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
ans.ldpaths.extend(pkg_config(dep, '--libs')) ans.ldpaths.extend(pkg_config(dep, '--libs'))
elif module == 'cocoa': elif module == 'cocoa':
ans.cppflags.append('-DGL_SILENCE_DEPRECATION')
for f in 'Cocoa IOKit CoreFoundation CoreVideo'.split(): for f in 'Cocoa IOKit CoreFoundation CoreVideo'.split():
ans.ldpaths.extend(('-framework', f)) ans.ldpaths.extend(('-framework', f))
@@ -88,7 +74,8 @@ def init_env(env, pkg_config, at_least_version, test_compile, module='x11'):
return ans return ans
def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir): def build_wayland_protocols(env, Command, parallel_run, emphasis, newer, dest_dir):
items = []
for protocol in env.wayland_protocols: for protocol in env.wayland_protocols:
src = os.path.join(env.wayland_packagedir, protocol) src = os.path.join(env.wayland_packagedir, protocol)
if not os.path.exists(src): if not os.path.exists(src):
@@ -98,8 +85,12 @@ def build_wayland_protocols(env, run_tool, emphasis, newer, dest_dir):
dest = os.path.join(dest_dir, dest) dest = os.path.join(dest_dir, dest)
if newer(dest, src): if newer(dest, src):
q = 'client-header' if ext == 'h' else env.wayland_scanner_code q = 'client-header' if ext == 'h' else env.wayland_scanner_code
run_tool([env.wayland_scanner, q, src, dest], items.append(Command(
desc='Generating {} ...'.format(emphasis(os.path.basename(dest)))) 'Generating {} ...'.format(emphasis(os.path.basename(dest))),
[env.wayland_scanner, q, src, dest],
lambda: True, None, None, None))
if items:
parallel_run(items)
class Arg: class Arg:
@@ -156,7 +147,8 @@ class Function:
def generate_wrappers(glfw_header): def generate_wrappers(glfw_header):
src = open(glfw_header).read() with open(glfw_header) as f:
src = f.read()
functions = [] functions = []
first = None first = None
for m in re.finditer(r'^GLFWAPI\s+(.+[)]);\s*$', src, flags=re.MULTILINE): for m in re.finditer(r'^GLFWAPI\s+(.+[)]);\s*$', src, flags=re.MULTILINE):

201
glfw/glfw3.h vendored
View File

@@ -1,9 +1,9 @@
/************************************************************************* /*************************************************************************
* GLFW 3.3 - www.glfw.org * GLFW 3.4 - www.glfw.org
* A library for OpenGL, window and input * A library for OpenGL, window and input
*------------------------------------------------------------------------ *------------------------------------------------------------------------
* Copyright (c) 2002-2006 Marcus Geelnard * Copyright (c) 2002-2006 Marcus Geelnard
* Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> * Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
* *
* This software is provided 'as-is', without any express or implied * This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages * warranty. In no event will the authors be held liable for any damages
@@ -261,7 +261,7 @@ extern "C" {
* backward-compatible. * backward-compatible.
* @ingroup init * @ingroup init
*/ */
#define GLFW_VERSION_MINOR 3 #define GLFW_VERSION_MINOR 4
/*! @brief The revision number of the GLFW library. /*! @brief The revision number of the GLFW library.
* *
* This is incremented when a bug fix release is made that does not contain any * This is incremented when a bug fix release is made that does not contain any
@@ -324,7 +324,7 @@ extern "C" {
* *
* The naming of the key codes follow these rules: * The naming of the key codes follow these rules:
* - The US keyboard layout is used * - The US keyboard layout is used
* - Names of printable alpha-numeric characters are used (e.g. "A", "R", * - Names of printable alphanumeric characters are used (e.g. "A", "R",
* "3", etc.) * "3", etc.)
* - For non-alphanumeric characters, Unicode:ish names are used (e.g. * - For non-alphanumeric characters, Unicode:ish names are used (e.g.
* "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not * "COMMA", "LEFT_SQUARE_BRACKET", etc.). Note that some names do not
@@ -342,7 +342,15 @@ extern "C" {
/* Printable keys */ /* Printable keys */
#define GLFW_KEY_SPACE 32 #define GLFW_KEY_SPACE 32
#define GLFW_KEY_EXCLAM 33 /* ! */
#define GLFW_KEY_DOUBLE_QUOTE 34 /* " */
#define GLFW_KEY_NUMBER_SIGN 35 /* # */
#define GLFW_KEY_DOLLAR 36 /* $ */
#define GLFW_KEY_AMPERSAND 38 /* & */
#define GLFW_KEY_APOSTROPHE 39 /* ' */ #define GLFW_KEY_APOSTROPHE 39 /* ' */
#define GLFW_KEY_PARENTHESIS_LEFT 40 /* ( */
#define GLFW_KEY_PARENTHESIS_RIGHT 41 /* ) */
#define GLFW_KEY_PLUS 43 /* + */
#define GLFW_KEY_COMMA 44 /* , */ #define GLFW_KEY_COMMA 44 /* , */
#define GLFW_KEY_MINUS 45 /* - */ #define GLFW_KEY_MINUS 45 /* - */
#define GLFW_KEY_PERIOD 46 /* . */ #define GLFW_KEY_PERIOD 46 /* . */
@@ -357,8 +365,12 @@ extern "C" {
#define GLFW_KEY_7 55 #define GLFW_KEY_7 55
#define GLFW_KEY_8 56 #define GLFW_KEY_8 56
#define GLFW_KEY_9 57 #define GLFW_KEY_9 57
#define GLFW_KEY_COLON 58 /* : */
#define GLFW_KEY_SEMICOLON 59 /* ; */ #define GLFW_KEY_SEMICOLON 59 /* ; */
#define GLFW_KEY_LESS 60 /* < */
#define GLFW_KEY_EQUAL 61 /* = */ #define GLFW_KEY_EQUAL 61 /* = */
#define GLFW_KEY_GREATER 62 /* > */
#define GLFW_KEY_AT 64 /* @ */
#define GLFW_KEY_A 65 #define GLFW_KEY_A 65
#define GLFW_KEY_B 66 #define GLFW_KEY_B 66
#define GLFW_KEY_C 67 #define GLFW_KEY_C 67
@@ -388,11 +400,62 @@ extern "C" {
#define GLFW_KEY_LEFT_BRACKET 91 /* [ */ #define GLFW_KEY_LEFT_BRACKET 91 /* [ */
#define GLFW_KEY_BACKSLASH 92 /* \ */ #define GLFW_KEY_BACKSLASH 92 /* \ */
#define GLFW_KEY_RIGHT_BRACKET 93 /* ] */ #define GLFW_KEY_RIGHT_BRACKET 93 /* ] */
#define GLFW_KEY_UNDERSCORE 95 /* _ */
#define GLFW_KEY_GRAVE_ACCENT 96 /* ` */ #define GLFW_KEY_GRAVE_ACCENT 96 /* ` */
#define GLFW_KEY_WORLD_1 161 /* non-US #1 */ #define GLFW_KEY_WORLD_1 161 /* non-US #1 */
#define GLFW_KEY_WORLD_2 162 /* non-US #2 */ #define GLFW_KEY_WORLD_2 162 /* non-US #2 */
#define GLFW_KEY_PLUS 163 #define GLFW_KEY_PARAGRAPH 167 /* § */
#define GLFW_KEY_UNDERSCORE 164 #define GLFW_KEY_MASCULINE 186 /* º */
#define GLFW_KEY_A_GRAVE 192 /* À */
#define GLFW_KEY_A_DIAERESIS 196 /* Ä */
#define GLFW_KEY_A_RING 197 /* Å */
#define GLFW_KEY_AE 198 /* Æ */
#define GLFW_KEY_C_CEDILLA 199 /* Ç */
#define GLFW_KEY_E_GRAVE 200 /* È */
#define GLFW_KEY_E_ACUTE 201 /* É */
#define GLFW_KEY_I_GRAVE 204 /* Ì */
#define GLFW_KEY_N_TILDE 209 /* Ñ */
#define GLFW_KEY_O_GRAVE 210 /* Ò */
#define GLFW_KEY_O_DIAERESIS 214 /* Ö */
#define GLFW_KEY_O_SLASH 216 /* Ø */
#define GLFW_KEY_U_GRAVE 217 /* Ù */
#define GLFW_KEY_U_DIAERESIS 220 /* Ü */
#define GLFW_KEY_S_SHARP 222 /* ß */
#define GLFW_KEY_CYRILLIC_A 223 /* А */
#define GLFW_KEY_CYRILLIC_BE 224 /* Б */
#define GLFW_KEY_CYRILLIC_VE 225 /* В */
#define GLFW_KEY_CYRILLIC_GHE 226 /* Г */
#define GLFW_KEY_CYRILLIC_DE 227 /* Д */
#define GLFW_KEY_CYRILLIC_IE 228 /* Е */
#define GLFW_KEY_CYRILLIC_ZHE 229 /* Ж */
#define GLFW_KEY_CYRILLIC_ZE 230 /* З */
#define GLFW_KEY_CYRILLIC_I 231 /* И */
#define GLFW_KEY_CYRILLIC_SHORT_I 232 /* Й */
#define GLFW_KEY_CYRILLIC_KA 233 /* К */
#define GLFW_KEY_CYRILLIC_EL 234 /* Л */
#define GLFW_KEY_CYRILLIC_EM 235 /* М */
#define GLFW_KEY_CYRILLIC_EN 236 /* Н */
#define GLFW_KEY_CYRILLIC_O 237 /* О */
#define GLFW_KEY_CYRILLIC_PE 238 /* П */
#define GLFW_KEY_CYRILLIC_ER 239 /* Р */
#define GLFW_KEY_CYRILLIC_ES 240 /* С */
#define GLFW_KEY_CYRILLIC_TE 241 /* Т */
#define GLFW_KEY_CYRILLIC_U 242 /* У */
#define GLFW_KEY_CYRILLIC_EF 243 /* Ф */
#define GLFW_KEY_CYRILLIC_HA 244 /* Х */
#define GLFW_KEY_CYRILLIC_TSE 245 /* Ц */
#define GLFW_KEY_CYRILLIC_CHE 246 /* Ч */
#define GLFW_KEY_CYRILLIC_SHA 247 /* Ш */
#define GLFW_KEY_CYRILLIC_SHCHA 248 /* Щ */
#define GLFW_KEY_CYRILLIC_HARD_SIGN 249 /* Ъ */
#define GLFW_KEY_CYRILLIC_YERU 250 /* Ы */
#define GLFW_KEY_CYRILLIC_SOFT_SIGN 251 /* Ь */
#define GLFW_KEY_CYRILLIC_E 252 /* Э */
#define GLFW_KEY_CYRILLIC_YU 253 /* Ю */
#define GLFW_KEY_CYRILLIC_YA 254 /* Я */
#define GLFW_KEY_CYRILLIC_IO 255 /* Ё */
#define GLFW_KEY_LAST_PRINTABLE GLFW_KEY_CYRILLIC_IO
/* Function keys */ /* Function keys */
#define GLFW_KEY_ESCAPE 256 #define GLFW_KEY_ESCAPE 256
@@ -905,62 +968,62 @@ extern "C" {
#define GLFW_CLIENT_API 0x00022001 #define GLFW_CLIENT_API 0x00022001
/*! @brief Context client API major version hint and attribute. /*! @brief Context client API major version hint and attribute.
* *
* Context client API major version [hint](@ref GLFW_CLIENT_API_hint) and * Context client API major version [hint](@ref GLFW_CONTEXT_VERSION_MAJOR_hint)
* [attribute](@ref GLFW_CLIENT_API_attrib). * and [attribute](@ref GLFW_CONTEXT_VERSION_MAJOR_attrib).
*/ */
#define GLFW_CONTEXT_VERSION_MAJOR 0x00022002 #define GLFW_CONTEXT_VERSION_MAJOR 0x00022002
/*! @brief Context client API minor version hint and attribute. /*! @brief Context client API minor version hint and attribute.
* *
* Context client API minor version [hint](@ref GLFW_CLIENT_API_hint) and * Context client API minor version [hint](@ref GLFW_CONTEXT_VERSION_MINOR_hint)
* [attribute](@ref GLFW_CLIENT_API_attrib). * and [attribute](@ref GLFW_CONTEXT_VERSION_MINOR_attrib).
*/ */
#define GLFW_CONTEXT_VERSION_MINOR 0x00022003 #define GLFW_CONTEXT_VERSION_MINOR 0x00022003
/*! @brief Context client API revision number hint and attribute. /*! @brief Context client API revision number hint and attribute.
* *
* Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and * Context client API revision number
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_CONTEXT_REVISION_attrib).
*/ */
#define GLFW_CONTEXT_REVISION 0x00022004 #define GLFW_CONTEXT_REVISION 0x00022004
/*! @brief Context robustness hint and attribute. /*! @brief Context robustness hint and attribute.
* *
* Context client API revision number [hint](@ref GLFW_CLIENT_API_hint) and * Context client API revision number [hint](@ref GLFW_CONTEXT_ROBUSTNESS_hint)
* [attribute](@ref GLFW_CLIENT_API_attrib). * and [attribute](@ref GLFW_CONTEXT_ROBUSTNESS_attrib).
*/ */
#define GLFW_CONTEXT_ROBUSTNESS 0x00022005 #define GLFW_CONTEXT_ROBUSTNESS 0x00022005
/*! @brief OpenGL forward-compatibility hint and attribute. /*! @brief OpenGL forward-compatibility hint and attribute.
* *
* OpenGL forward-compatibility [hint](@ref GLFW_CLIENT_API_hint) and * OpenGL forward-compatibility [hint](@ref GLFW_OPENGL_FORWARD_COMPAT_hint)
* [attribute](@ref GLFW_CLIENT_API_attrib). * and [attribute](@ref GLFW_OPENGL_FORWARD_COMPAT_attrib).
*/ */
#define GLFW_OPENGL_FORWARD_COMPAT 0x00022006 #define GLFW_OPENGL_FORWARD_COMPAT 0x00022006
/*! @brief OpenGL debug context hint and attribute. /*! @brief OpenGL debug context hint and attribute.
* *
* OpenGL debug context [hint](@ref GLFW_CLIENT_API_hint) and * OpenGL debug context [hint](@ref GLFW_OPENGL_DEBUG_CONTEXT_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_OPENGL_DEBUG_CONTEXT_attrib).
*/ */
#define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007 #define GLFW_OPENGL_DEBUG_CONTEXT 0x00022007
/*! @brief OpenGL profile hint and attribute. /*! @brief OpenGL profile hint and attribute.
* *
* OpenGL profile [hint](@ref GLFW_CLIENT_API_hint) and * OpenGL profile [hint](@ref GLFW_OPENGL_PROFILE_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_OPENGL_PROFILE_attrib).
*/ */
#define GLFW_OPENGL_PROFILE 0x00022008 #define GLFW_OPENGL_PROFILE 0x00022008
/*! @brief Context flush-on-release hint and attribute. /*! @brief Context flush-on-release hint and attribute.
* *
* Context flush-on-release [hint](@ref GLFW_CLIENT_API_hint) and * Context flush-on-release [hint](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_CONTEXT_RELEASE_BEHAVIOR_attrib).
*/ */
#define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009 #define GLFW_CONTEXT_RELEASE_BEHAVIOR 0x00022009
/*! @brief Context error suppression hint and attribute. /*! @brief Context error suppression hint and attribute.
* *
* Context error suppression [hint](@ref GLFW_CLIENT_API_hint) and * Context error suppression [hint](@ref GLFW_CONTEXT_NO_ERROR_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_CONTEXT_NO_ERROR_attrib).
*/ */
#define GLFW_CONTEXT_NO_ERROR 0x0002200A #define GLFW_CONTEXT_NO_ERROR 0x0002200A
/*! @brief Context creation API hint and attribute. /*! @brief Context creation API hint and attribute.
* *
* Context creation API [hint](@ref GLFW_CLIENT_API_hint) and * Context creation API [hint](@ref GLFW_CONTEXT_CREATION_API_hint) and
* [attribute](@ref GLFW_CLIENT_API_attrib). * [attribute](@ref GLFW_CONTEXT_CREATION_API_attrib).
*/ */
#define GLFW_CONTEXT_CREATION_API 0x0002200B #define GLFW_CONTEXT_CREATION_API 0x0002200B
/*! @brief Window content area scaling window /*! @brief Window content area scaling window
@@ -1405,7 +1468,7 @@ typedef void (* GLFWscrollfun)(GLFWwindow*,double,double,int);
* @param[in] mods Bit field describing which [modifier keys](@ref mods) were * @param[in] mods Bit field describing which [modifier keys](@ref mods) were
* held down. * held down.
* @param[in] text UTF-8 encoded text generated by this key event or empty string. * @param[in] text UTF-8 encoded text generated by this key event or empty string.
* @param[in] Used for Input Method events. Zero for normal key events. * @param[in] status Used for Input Method events. Zero for normal key events.
* A value of 1 means the pre-edit text for the input event has been changed. * A value of 1 means the pre-edit text for the input event has been changed.
* A value of 2 means the text should be committed. * A value of 2 means the text should be committed.
* *
@@ -1628,7 +1691,6 @@ typedef struct GLFWgamepadstate
GLFWAPI int glfwInit(void); GLFWAPI int glfwInit(void);
GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data); GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *callback_data);
GLFWAPI void glfwStopMainLoop(void); GLFWAPI void glfwStopMainLoop(void);
GLFWAPI void glfwRequestTickCallback(void);
GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback); GLFWAPI unsigned long long glfwAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void * callback_data, GLFWuserdatafun free_callback);
GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled); GLFWAPI void glfwUpdateTimer(unsigned long long timer_id, double interval, bool enabled);
GLFWAPI void glfwRemoveTimer(unsigned long long); GLFWAPI void glfwRemoveTimer(unsigned long long);
@@ -2176,7 +2238,7 @@ GLFWAPI const GLFWvidmode* glfwGetVideoMode(GLFWmonitor* monitor);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED, @ref
* GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR. * GLFW_INVALID_VALUE and @ref GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Gamma handling is a priviledged protocol, this function * @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
* *
* @thread_safety This function must only be called from the main thread. * @thread_safety This function must only be called from the main thread.
@@ -2200,7 +2262,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* monitor, float gamma);
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref * @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
* GLFW_PLATFORM_ERROR. * GLFW_PLATFORM_ERROR.
* *
* @remark @wayland Gamma handling is a priviledged protocol, this function * @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR while
* returning `NULL`. * returning `NULL`.
* *
@@ -2244,7 +2306,7 @@ GLFWAPI const GLFWgammaramp* glfwGetGammaRamp(GLFWmonitor* monitor);
* *
* @remark @win32 The gamma ramp size must be 256. * @remark @win32 The gamma ramp size must be 256.
* *
* @remark @wayland Gamma handling is a priviledged protocol, this function * @remark @wayland Gamma handling is a privileged protocol, this function
* will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR. * will thus never be implemented and emits @ref GLFW_PLATFORM_ERROR.
* *
* @pointer_lifetime The specified gamma ramp is copied before this function * @pointer_lifetime The specified gamma ramp is copied before this function
@@ -2463,7 +2525,7 @@ GLFWAPI void glfwWindowHintString(int hint, const char* value);
* *
* @remark @macos When activating frame autosaving with * @remark @macos When activating frame autosaving with
* [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified * [GLFW_COCOA_FRAME_NAME](@ref GLFW_COCOA_FRAME_NAME_hint), the specified
* window size and position may be overriden by previously saved values. * window size and position may be overridden by previously saved values.
* *
* @remark @x11 Some window managers will not respect the placement of * @remark @x11 Some window managers will not respect the placement of
* initially hidden windows. * initially hidden windows.
@@ -3845,20 +3907,85 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* window, int mode, int value);
* [key callback](@ref input_key) without modification. * [key callback](@ref input_key) without modification.
* *
* The printable keys are: * The printable keys are:
* - `GLFW_KEY_SPACE`
* - `GLFW_KEY_EXCLAM`
* - `GLFW_KEY_DOUBLE_QUOTE`
* - `GLFW_KEY_NUMBER_SIGN`
* - `GLFW_KEY_DOLLAR`
* - `GLFW_KEY_AMPERSAND`
* - `GLFW_KEY_APOSTROPHE` * - `GLFW_KEY_APOSTROPHE`
* - `GLFW_KEY_PARENTHESIS_LEFT`
* - `GLFW_KEY_PARENTHESIS_RIGHT`
* - `GLFW_KEY_PLUS`
* - `GLFW_KEY_COMMA` * - `GLFW_KEY_COMMA`
* - `GLFW_KEY_MINUS` * - `GLFW_KEY_MINUS`
* - `GLFW_KEY_PERIOD` * - `GLFW_KEY_PERIOD`
* - `GLFW_KEY_SLASH` * - `GLFW_KEY_SLASH`
* - `GLFW_KEY_0` to `GLFW_KEY_9`
* - `GLFW_KEY_COLON`
* - `GLFW_KEY_SEMICOLON` * - `GLFW_KEY_SEMICOLON`
* - `GLFW_KEY_LESS`
* - `GLFW_KEY_EQUAL` * - `GLFW_KEY_EQUAL`
* - `GLFW_KEY_GREATER`
* - `GLFW_KEY_AT`
* - `GLFW_KEY_A` to `GLFW_KEY_Z`
* - `GLFW_KEY_LEFT_BRACKET` * - `GLFW_KEY_LEFT_BRACKET`
* - `GLFW_KEY_RIGHT_BRACKET`
* - `GLFW_KEY_BACKSLASH` * - `GLFW_KEY_BACKSLASH`
* - `GLFW_KEY_RIGHT_BRACKET`
* - `GLFW_KEY_UNDERSCORE`
* - `GLFW_KEY_GRAVE_ACCENT`
* - `GLFW_KEY_WORLD_1` * - `GLFW_KEY_WORLD_1`
* - `GLFW_KEY_WORLD_2` * - `GLFW_KEY_WORLD_2`
* - `GLFW_KEY_0` to `GLFW_KEY_9` * - `GLFW_KEY_PARAGRAPH`
* - `GLFW_KEY_A` to `GLFW_KEY_Z` * - `GLFW_KEY_MASCULINE`
* - `GLFW_KEY_A_GRAVE`
* - `GLFW_KEY_A_DIAERESIS`
* - `GLFW_KEY_A_RING`
* - `GLFW_KEY_AE`
* - `GLFW_KEY_C_CEDILLA`
* - `GLFW_KEY_E_GRAVE`
* - `GLFW_KEY_E_ACUTE`
* - `GLFW_KEY_I_GRAVE`
* - `GLFW_KEY_N_TILDE`
* - `GLFW_KEY_O_GRAVE`
* - `GLFW_KEY_O_DIAERESIS`
* - `GLFW_KEY_O_SLASH`
* - `GLFW_KEY_U_GRAVE`
* - `GLFW_KEY_U_DIAERESIS`
* - `GLFW_KEY_S_SHARP`
* - `GLFW_KEY_CYRILLIC_A`
* - `GLFW_KEY_CYRILLIC_BE`
* - `GLFW_KEY_CYRILLIC_VE`
* - `GLFW_KEY_CYRILLIC_GHE`
* - `GLFW_KEY_CYRILLIC_DE`
* - `GLFW_KEY_CYRILLIC_IE`
* - `GLFW_KEY_CYRILLIC_ZHE`
* - `GLFW_KEY_CYRILLIC_ZE`
* - `GLFW_KEY_CYRILLIC_I`
* - `GLFW_KEY_CYRILLIC_SHORT_I`
* - `GLFW_KEY_CYRILLIC_KA`
* - `GLFW_KEY_CYRILLIC_EL`
* - `GLFW_KEY_CYRILLIC_EM`
* - `GLFW_KEY_CYRILLIC_EN`
* - `GLFW_KEY_CYRILLIC_O`
* - `GLFW_KEY_CYRILLIC_PE`
* - `GLFW_KEY_CYRILLIC_ER`
* - `GLFW_KEY_CYRILLIC_ES`
* - `GLFW_KEY_CYRILLIC_TE`
* - `GLFW_KEY_CYRILLIC_U`
* - `GLFW_KEY_CYRILLIC_EF`
* - `GLFW_KEY_CYRILLIC_HA`
* - `GLFW_KEY_CYRILLIC_TSE`
* - `GLFW_KEY_CYRILLIC_CHE`
* - `GLFW_KEY_CYRILLIC_SHA`
* - `GLFW_KEY_CYRILLIC_SHCHA`
* - `GLFW_KEY_CYRILLIC_HARD_SIGN`
* - `GLFW_KEY_CYRILLIC_YERU`
* - `GLFW_KEY_CYRILLIC_SOFT_SIGN`
* - `GLFW_KEY_CYRILLIC_E`
* - `GLFW_KEY_CYRILLIC_YU`
* - `GLFW_KEY_CYRILLIC_YA`
* - `GLFW_KEY_CYRILLIC_IO`
* - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9` * - `GLFW_KEY_KP_0` to `GLFW_KEY_KP_9`
* - `GLFW_KEY_KP_DECIMAL` * - `GLFW_KEY_KP_DECIMAL`
* - `GLFW_KEY_KP_DIVIDE` * - `GLFW_KEY_KP_DIVIDE`
@@ -4525,7 +4652,7 @@ GLFWAPI const unsigned char* glfwGetJoystickHats(int jid, int* count);
*/ */
GLFWAPI const char* glfwGetJoystickName(int jid); GLFWAPI const char* glfwGetJoystickName(int jid);
/*! @brief Returns the SDL comaptible GUID of the specified joystick. /*! @brief Returns the SDL compatible GUID of the specified joystick.
* *
* This function returns the SDL compatible GUID, as a UTF-8 encoded * This function returns the SDL compatible GUID, as a UTF-8 encoded
* hexadecimal string, of the specified joystick. The returned string is * hexadecimal string, of the specified joystick. The returned string is
@@ -4739,7 +4866,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
/*! @brief Retrieves the state of the specified joystick remapped as a gamepad. /*! @brief Retrieves the state of the specified joystick remapped as a gamepad.
* *
* This function retrives the state of the specified joystick remapped to * This function retrieves the state of the specified joystick remapped to
* an Xbox-like gamepad. * an Xbox-like gamepad.
* *
* If the specified joystick is not present or does not have a gamepad mapping * If the specified joystick is not present or does not have a gamepad mapping

66
glfw/glx_context.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 GLX - www.glfw.org // GLFW 3.4 GLX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -142,7 +144,7 @@ static bool chooseGLXFBConfig(const _GLFWfbconfig* desired,
// Create the OpenGL context using legacy API // Create the OpenGL context using legacy API
// //
static GLXContext createLegacyContextGLX(_GLFWwindow* window, static GLXContext createLegacyContextGLX(_GLFWwindow* window UNUSED,
GLXFBConfig fbconfig, GLXFBConfig fbconfig,
GLXContext share) GLXContext share)
{ {
@@ -222,8 +224,11 @@ static GLFWglproc getProcAddressGLX(const char* procname)
return _glfw.glx.GetProcAddress((const GLubyte*) procname); return _glfw.glx.GetProcAddress((const GLubyte*) procname);
else if (_glfw.glx.GetProcAddressARB) else if (_glfw.glx.GetProcAddressARB)
return _glfw.glx.GetProcAddressARB((const GLubyte*) procname); return _glfw.glx.GetProcAddressARB((const GLubyte*) procname);
else else {
return _glfw_dlsym(_glfw.glx.handle, procname); GLFWglproc ans = NULL;
glfw_dlsym(ans, _glfw.glx.handle, procname);
return ans;
}
} }
static void destroyContextGLX(_GLFWwindow* window) static void destroyContextGLX(_GLFWwindow* window)
@@ -280,36 +285,21 @@ bool _glfwInitGLX(void)
return false; return false;
} }
_glfw.glx.GetFBConfigs = glfw_dlsym(_glfw.glx.GetFBConfigs, _glfw.glx.handle, "glXGetFBConfigs");
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigs"); glfw_dlsym(_glfw.glx.GetFBConfigAttrib, _glfw.glx.handle, "glXGetFBConfigAttrib");
_glfw.glx.GetFBConfigAttrib = glfw_dlsym(_glfw.glx.GetClientString, _glfw.glx.handle, "glXGetClientString");
_glfw_dlsym(_glfw.glx.handle, "glXGetFBConfigAttrib"); glfw_dlsym(_glfw.glx.QueryExtension, _glfw.glx.handle, "glXQueryExtension");
_glfw.glx.GetClientString = glfw_dlsym(_glfw.glx.QueryVersion, _glfw.glx.handle, "glXQueryVersion");
_glfw_dlsym(_glfw.glx.handle, "glXGetClientString"); glfw_dlsym(_glfw.glx.DestroyContext, _glfw.glx.handle, "glXDestroyContext");
_glfw.glx.QueryExtension = glfw_dlsym(_glfw.glx.MakeCurrent, _glfw.glx.handle, "glXMakeCurrent");
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtension"); glfw_dlsym(_glfw.glx.SwapBuffers, _glfw.glx.handle, "glXSwapBuffers");
_glfw.glx.QueryVersion = glfw_dlsym(_glfw.glx.QueryExtensionsString, _glfw.glx.handle, "glXQueryExtensionsString");
_glfw_dlsym(_glfw.glx.handle, "glXQueryVersion"); glfw_dlsym(_glfw.glx.CreateNewContext, _glfw.glx.handle, "glXCreateNewContext");
_glfw.glx.DestroyContext = glfw_dlsym(_glfw.glx.CreateWindow, _glfw.glx.handle, "glXCreateWindow");
_glfw_dlsym(_glfw.glx.handle, "glXDestroyContext"); glfw_dlsym(_glfw.glx.DestroyWindow, _glfw.glx.handle, "glXDestroyWindow");
_glfw.glx.MakeCurrent = glfw_dlsym(_glfw.glx.GetProcAddress, _glfw.glx.handle, "glXGetProcAddress");
_glfw_dlsym(_glfw.glx.handle, "glXMakeCurrent"); glfw_dlsym(_glfw.glx.GetProcAddressARB, _glfw.glx.handle, "glXGetProcAddressARB");
_glfw.glx.SwapBuffers = glfw_dlsym(_glfw.glx.GetVisualFromFBConfig, _glfw.glx.handle, "glXGetVisualFromFBConfig");
_glfw_dlsym(_glfw.glx.handle, "glXSwapBuffers");
_glfw.glx.QueryExtensionsString =
_glfw_dlsym(_glfw.glx.handle, "glXQueryExtensionsString");
_glfw.glx.CreateNewContext =
_glfw_dlsym(_glfw.glx.handle, "glXCreateNewContext");
_glfw.glx.CreateWindow =
_glfw_dlsym(_glfw.glx.handle, "glXCreateWindow");
_glfw.glx.DestroyWindow =
_glfw_dlsym(_glfw.glx.handle, "glXDestroyWindow");
_glfw.glx.GetProcAddress =
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddress");
_glfw.glx.GetProcAddressARB =
_glfw_dlsym(_glfw.glx.handle, "glXGetProcAddressARB");
_glfw.glx.GetVisualFromFBConfig =
_glfw_dlsym(_glfw.glx.handle, "glXGetVisualFromFBConfig");
if (!_glfw.glx.GetFBConfigs || if (!_glfw.glx.GetFBConfigs ||
!_glfw.glx.GetFBConfigAttrib || !_glfw.glx.GetFBConfigAttrib ||
@@ -433,7 +423,7 @@ void _glfwTerminateGLX(void)
#define setAttrib(a, v) \ #define setAttrib(a, v) \
{ \ { \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \ attribs[index++] = a; \
attribs[index++] = v; \ attribs[index++] = v; \
} }
@@ -631,8 +621,8 @@ bool _glfwCreateContextGLX(_GLFWwindow* window,
// Returns the Visual and depth of the chosen GLXFBConfig // Returns the Visual and depth of the chosen GLXFBConfig
// //
bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig, bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig UNUSED,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig UNUSED,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth) Visual** visual, int* depth)
{ {

33
glfw/glx_context.h vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 GLX - www.glfw.org // GLFW 3.4 GLX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -107,8 +107,8 @@ typedef GLXContext (*PFNGLXCREATECONTEXTATTRIBSARBPROC)(Display*,GLXFBConfig,GLX
#define glXCreateWindow _glfw.glx.CreateWindow #define glXCreateWindow _glfw.glx.CreateWindow
#define glXDestroyWindow _glfw.glx.DestroyWindow #define glXDestroyWindow _glfw.glx.DestroyWindow
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextGLX glx;
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryGLX glx;
// GLX-specific per-context data // GLX-specific per-context data
@@ -153,18 +153,18 @@ typedef struct _GLFWlibraryGLX
PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT; PFNGLXSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA; PFNGLXSWAPINTERVALMESAPROC SwapIntervalMESA;
PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB; PFNGLXCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool SGI_swap_control; bool SGI_swap_control;
bool EXT_swap_control; bool EXT_swap_control;
bool MESA_swap_control; bool MESA_swap_control;
bool ARB_multisample; bool ARB_multisample;
bool ARB_framebuffer_sRGB; bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB; bool EXT_framebuffer_sRGB;
bool ARB_create_context; bool ARB_create_context;
bool ARB_create_context_profile; bool ARB_create_context_profile;
bool ARB_create_context_robustness; bool ARB_create_context_robustness;
bool EXT_create_context_es2_profile; bool EXT_create_context_es2_profile;
bool ARB_create_context_no_error; bool ARB_create_context_no_error;
bool ARB_context_flush_control; bool ARB_context_flush_control;
} _GLFWlibraryGLX; } _GLFWlibraryGLX;
@@ -178,4 +178,3 @@ bool _glfwChooseVisualGLX(const _GLFWwndconfig* wndconfig,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig, const _GLFWfbconfig* fbconfig,
Visual** visual, int* depth); Visual** visual, int* depth);

8
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> // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
// //
@@ -57,7 +57,7 @@ test_env_var(const char *name, const char *val) {
} }
static inline size_t static inline size_t
MIN(size_t a, size_t b) { GLFW_MIN(size_t a, size_t b) {
return a < b ? a : b; return a < b ? a : b;
} }
@@ -117,7 +117,7 @@ send_text(const char *text, int state) {
// Connection handling {{{ // Connection handling {{{
static DBusHandlerResult static DBusHandlerResult
message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) { message_handler(DBusConnection *conn UNUSED, DBusMessage *msg, void *user_data) {
// To monitor signals from IBUS, use // To monitor signals from IBUS, use
//  dbus-monitor --address `ibus address` "type='signal',interface='org.freedesktop.IBus.InputContext'" //  dbus-monitor --address `ibus address` "type='signal',interface='org.freedesktop.IBus.InputContext'"
_GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data; _GLFWIBUSData *ibus = (_GLFWIBUSData*)user_data;
@@ -151,7 +151,7 @@ get_ibus_address_file_name(void) {
addr = getenv("IBUS_ADDRESS"); addr = getenv("IBUS_ADDRESS");
int offset = 0; int offset = 0;
if (addr && addr[0]) { if (addr && addr[0]) {
memcpy(ans, addr, MIN(strlen(addr), sizeof(ans))); memcpy(ans, addr, GLFW_MIN(strlen(addr), sizeof(ans)));
return ans; return ans;
} }

2
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> // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
// //

10
glfw/init.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
#include "mappings.h" #include "mappings.h"
@@ -342,10 +344,6 @@ GLFWAPI void glfwRunMainLoop(GLFWtickcallback callback, void *data)
_glfwPlatformRunMainLoop(callback, data); _glfwPlatformRunMainLoop(callback, data);
} }
GLFWAPI void glfwRequestTickCallback(void) {
_glfwPlatformRequestTickCallback();
}
GLFWAPI void glfwStopMainLoop(void) { GLFWAPI void glfwStopMainLoop(void) {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformStopMainLoop(); _glfwPlatformStopMainLoop();

337
glfw/input.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@@ -254,7 +256,7 @@ static bool parseMapping(_GLFWmapping* mapping, const char* string)
////// GLFW event API ////// ////// GLFW event API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// Notifies shared code of a key event // 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, int key, int scancode, int action, int mods, const char* text, int state)
{ {
@@ -409,7 +411,7 @@ _GLFWjoystick* _glfwAllocJoystick(const char* name,
js->present = true; js->present = true;
js->name = _glfw_strdup(name); js->name = _glfw_strdup(name);
js->axes = calloc(axisCount, sizeof(float)); js->axes = calloc(axisCount, sizeof(float));
js->buttons = calloc(buttonCount + hatCount * 4, 1); js->buttons = calloc(buttonCount + (size_t) hatCount * 4, 1);
js->hats = calloc(hatCount, 1); js->hats = calloc(hatCount, 1);
js->axisCount = axisCount; js->axisCount = axisCount;
js->buttonCount = buttonCount; js->buttonCount = buttonCount;
@@ -437,144 +439,207 @@ const char* _glfwGetKeyName(int key)
switch (key) switch (key)
{ {
// Printable keys // Printable keys
case GLFW_KEY_A: return "A"; case GLFW_KEY_SPACE: return "SPACE";
case GLFW_KEY_B: return "B"; case GLFW_KEY_EXCLAM: return "EXCLAM";
case GLFW_KEY_C: return "C"; case GLFW_KEY_DOUBLE_QUOTE: return "DOUBLE_QUOTE";
case GLFW_KEY_D: return "D"; case GLFW_KEY_NUMBER_SIGN: return "NUMBER_SIGN";
case GLFW_KEY_E: return "E"; case GLFW_KEY_DOLLAR: return "DOLLAR";
case GLFW_KEY_F: return "F"; case GLFW_KEY_AMPERSAND: return "AMPERSAND";
case GLFW_KEY_G: return "G"; case GLFW_KEY_APOSTROPHE: return "APOSTROPHE";
case GLFW_KEY_H: return "H"; case GLFW_KEY_PARENTHESIS_LEFT: return "PARENTHESIS_LEFT";
case GLFW_KEY_I: return "I"; case GLFW_KEY_PARENTHESIS_RIGHT: return "PARENTHESIS_RIGHT";
case GLFW_KEY_J: return "J"; case GLFW_KEY_PLUS: return "PLUS";
case GLFW_KEY_K: return "K"; case GLFW_KEY_COMMA: return "COMMA";
case GLFW_KEY_L: return "L"; case GLFW_KEY_MINUS: return "MINUS";
case GLFW_KEY_M: return "M"; case GLFW_KEY_PERIOD: return "PERIOD";
case GLFW_KEY_N: return "N"; case GLFW_KEY_SLASH: return "SLASH";
case GLFW_KEY_O: return "O"; case GLFW_KEY_0: return "0";
case GLFW_KEY_P: return "P"; case GLFW_KEY_1: return "1";
case GLFW_KEY_Q: return "Q"; case GLFW_KEY_2: return "2";
case GLFW_KEY_R: return "R"; case GLFW_KEY_3: return "3";
case GLFW_KEY_S: return "S"; case GLFW_KEY_4: return "4";
case GLFW_KEY_T: return "T"; case GLFW_KEY_5: return "5";
case GLFW_KEY_U: return "U"; case GLFW_KEY_6: return "6";
case GLFW_KEY_V: return "V"; case GLFW_KEY_7: return "7";
case GLFW_KEY_W: return "W"; case GLFW_KEY_8: return "8";
case GLFW_KEY_X: return "X"; case GLFW_KEY_9: return "9";
case GLFW_KEY_Y: return "Y"; case GLFW_KEY_COLON: return "COLON";
case GLFW_KEY_Z: return "Z"; case GLFW_KEY_SEMICOLON: return "SEMICOLON";
case GLFW_KEY_1: return "1"; case GLFW_KEY_LESS: return "LESS";
case GLFW_KEY_2: return "2"; case GLFW_KEY_EQUAL: return "EQUAL";
case GLFW_KEY_3: return "3"; case GLFW_KEY_GREATER: return "GREATER";
case GLFW_KEY_4: return "4"; case GLFW_KEY_AT: return "AT";
case GLFW_KEY_5: return "5"; case GLFW_KEY_A: return "A";
case GLFW_KEY_6: return "6"; case GLFW_KEY_B: return "B";
case GLFW_KEY_7: return "7"; case GLFW_KEY_C: return "C";
case GLFW_KEY_8: return "8"; case GLFW_KEY_D: return "D";
case GLFW_KEY_9: return "9"; case GLFW_KEY_E: return "E";
case GLFW_KEY_0: return "0"; case GLFW_KEY_F: return "F";
case GLFW_KEY_SPACE: return "SPACE"; case GLFW_KEY_G: return "G";
case GLFW_KEY_MINUS: return "MINUS"; case GLFW_KEY_H: return "H";
case GLFW_KEY_EQUAL: return "EQUAL"; case GLFW_KEY_I: return "I";
case GLFW_KEY_LEFT_BRACKET: return "LEFT BRACKET"; case GLFW_KEY_J: return "J";
case GLFW_KEY_RIGHT_BRACKET: return "RIGHT BRACKET"; case GLFW_KEY_K: return "K";
case GLFW_KEY_BACKSLASH: return "BACKSLASH"; case GLFW_KEY_L: return "L";
case GLFW_KEY_SEMICOLON: return "SEMICOLON"; case GLFW_KEY_M: return "M";
case GLFW_KEY_APOSTROPHE: return "APOSTROPHE"; case GLFW_KEY_N: return "N";
case GLFW_KEY_GRAVE_ACCENT: return "GRAVE ACCENT"; case GLFW_KEY_O: return "O";
case GLFW_KEY_COMMA: return "COMMA"; case GLFW_KEY_P: return "P";
case GLFW_KEY_PERIOD: return "PERIOD"; case GLFW_KEY_Q: return "Q";
case GLFW_KEY_SLASH: return "SLASH"; case GLFW_KEY_R: return "R";
case GLFW_KEY_WORLD_1: return "WORLD 1"; case GLFW_KEY_S: return "S";
case GLFW_KEY_WORLD_2: return "WORLD 2"; case GLFW_KEY_T: return "T";
case GLFW_KEY_PLUS: return "PLUS"; case GLFW_KEY_U: return "U";
case GLFW_KEY_UNDERSCORE: return "UNDERSCORE"; 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_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 // Function keys
case GLFW_KEY_ESCAPE: return "ESCAPE"; case GLFW_KEY_ESCAPE: return "ESCAPE";
case GLFW_KEY_F1: return "F1"; case GLFW_KEY_F1: return "F1";
case GLFW_KEY_F2: return "F2"; case GLFW_KEY_F2: return "F2";
case GLFW_KEY_F3: return "F3"; case GLFW_KEY_F3: return "F3";
case GLFW_KEY_F4: return "F4"; case GLFW_KEY_F4: return "F4";
case GLFW_KEY_F5: return "F5"; case GLFW_KEY_F5: return "F5";
case GLFW_KEY_F6: return "F6"; case GLFW_KEY_F6: return "F6";
case GLFW_KEY_F7: return "F7"; case GLFW_KEY_F7: return "F7";
case GLFW_KEY_F8: return "F8"; case GLFW_KEY_F8: return "F8";
case GLFW_KEY_F9: return "F9"; case GLFW_KEY_F9: return "F9";
case GLFW_KEY_F10: return "F10"; case GLFW_KEY_F10: return "F10";
case GLFW_KEY_F11: return "F11"; case GLFW_KEY_F11: return "F11";
case GLFW_KEY_F12: return "F12"; case GLFW_KEY_F12: return "F12";
case GLFW_KEY_F13: return "F13"; case GLFW_KEY_F13: return "F13";
case GLFW_KEY_F14: return "F14"; case GLFW_KEY_F14: return "F14";
case GLFW_KEY_F15: return "F15"; case GLFW_KEY_F15: return "F15";
case GLFW_KEY_F16: return "F16"; case GLFW_KEY_F16: return "F16";
case GLFW_KEY_F17: return "F17"; case GLFW_KEY_F17: return "F17";
case GLFW_KEY_F18: return "F18"; case GLFW_KEY_F18: return "F18";
case GLFW_KEY_F19: return "F19"; case GLFW_KEY_F19: return "F19";
case GLFW_KEY_F20: return "F20"; case GLFW_KEY_F20: return "F20";
case GLFW_KEY_F21: return "F21"; case GLFW_KEY_F21: return "F21";
case GLFW_KEY_F22: return "F22"; case GLFW_KEY_F22: return "F22";
case GLFW_KEY_F23: return "F23"; case GLFW_KEY_F23: return "F23";
case GLFW_KEY_F24: return "F24"; case GLFW_KEY_F24: return "F24";
case GLFW_KEY_F25: return "F25"; case GLFW_KEY_F25: return "F25";
case GLFW_KEY_UP: return "UP"; case GLFW_KEY_UP: return "UP";
case GLFW_KEY_DOWN: return "DOWN"; case GLFW_KEY_DOWN: return "DOWN";
case GLFW_KEY_LEFT: return "LEFT"; case GLFW_KEY_LEFT: return "LEFT";
case GLFW_KEY_RIGHT: return "RIGHT"; case GLFW_KEY_RIGHT: return "RIGHT";
case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT"; case GLFW_KEY_LEFT_SHIFT: return "LEFT SHIFT";
case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT"; case GLFW_KEY_RIGHT_SHIFT: return "RIGHT SHIFT";
case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL"; case GLFW_KEY_LEFT_CONTROL: return "LEFT CONTROL";
case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL"; case GLFW_KEY_RIGHT_CONTROL: return "RIGHT CONTROL";
case GLFW_KEY_LEFT_ALT: return "LEFT ALT"; case GLFW_KEY_LEFT_ALT: return "LEFT ALT";
case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT"; case GLFW_KEY_RIGHT_ALT: return "RIGHT ALT";
case GLFW_KEY_TAB: return "TAB"; case GLFW_KEY_TAB: return "TAB";
case GLFW_KEY_ENTER: return "ENTER"; case GLFW_KEY_ENTER: return "ENTER";
case GLFW_KEY_BACKSPACE: return "BACKSPACE"; case GLFW_KEY_BACKSPACE: return "BACKSPACE";
case GLFW_KEY_INSERT: return "INSERT"; case GLFW_KEY_INSERT: return "INSERT";
case GLFW_KEY_DELETE: return "DELETE"; case GLFW_KEY_DELETE: return "DELETE";
case GLFW_KEY_PAGE_UP: return "PAGE UP"; case GLFW_KEY_PAGE_UP: return "PAGE UP";
case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN"; case GLFW_KEY_PAGE_DOWN: return "PAGE DOWN";
case GLFW_KEY_HOME: return "HOME"; case GLFW_KEY_HOME: return "HOME";
case GLFW_KEY_END: return "END"; case GLFW_KEY_END: return "END";
case GLFW_KEY_KP_0: return "KEYPAD 0"; case GLFW_KEY_KP_0: return "KEYPAD 0";
case GLFW_KEY_KP_1: return "KEYPAD 1"; case GLFW_KEY_KP_1: return "KEYPAD 1";
case GLFW_KEY_KP_2: return "KEYPAD 2"; case GLFW_KEY_KP_2: return "KEYPAD 2";
case GLFW_KEY_KP_3: return "KEYPAD 3"; case GLFW_KEY_KP_3: return "KEYPAD 3";
case GLFW_KEY_KP_4: return "KEYPAD 4"; case GLFW_KEY_KP_4: return "KEYPAD 4";
case GLFW_KEY_KP_5: return "KEYPAD 5"; case GLFW_KEY_KP_5: return "KEYPAD 5";
case GLFW_KEY_KP_6: return "KEYPAD 6"; case GLFW_KEY_KP_6: return "KEYPAD 6";
case GLFW_KEY_KP_7: return "KEYPAD 7"; case GLFW_KEY_KP_7: return "KEYPAD 7";
case GLFW_KEY_KP_8: return "KEYPAD 8"; case GLFW_KEY_KP_8: return "KEYPAD 8";
case GLFW_KEY_KP_9: return "KEYPAD 9"; case GLFW_KEY_KP_9: return "KEYPAD 9";
case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE"; case GLFW_KEY_KP_DIVIDE: return "KEYPAD DIVIDE";
case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTPLY"; case GLFW_KEY_KP_MULTIPLY: return "KEYPAD MULTIPLY";
case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT"; case GLFW_KEY_KP_SUBTRACT: return "KEYPAD SUBTRACT";
case GLFW_KEY_KP_ADD: return "KEYPAD ADD"; case GLFW_KEY_KP_ADD: return "KEYPAD ADD";
case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL"; case GLFW_KEY_KP_DECIMAL: return "KEYPAD DECIMAL";
case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL"; case GLFW_KEY_KP_EQUAL: return "KEYPAD EQUAL";
case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER"; case GLFW_KEY_KP_ENTER: return "KEYPAD ENTER";
case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN"; case GLFW_KEY_PRINT_SCREEN: return "PRINT SCREEN";
case GLFW_KEY_NUM_LOCK: return "NUM LOCK"; case GLFW_KEY_NUM_LOCK: return "NUM LOCK";
case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK"; case GLFW_KEY_CAPS_LOCK: return "CAPS LOCK";
case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK"; case GLFW_KEY_SCROLL_LOCK: return "SCROLL LOCK";
case GLFW_KEY_PAUSE: return "PAUSE"; case GLFW_KEY_PAUSE: return "PAUSE";
case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER"; case GLFW_KEY_LEFT_SUPER: return "LEFT SUPER";
case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER"; case GLFW_KEY_RIGHT_SUPER: return "RIGHT SUPER";
case GLFW_KEY_MENU: return "MENU"; case GLFW_KEY_MENU: return "MENU";
default: return "UNKNOWN"; default: return "UNKNOWN";
} }
} }
// Center the cursor in the middle of the content area of the specified window // Center the cursor in the content area of the specified window
// //
void _glfwCenterCursorInContentArea(_GLFWwindow* window) void _glfwCenterCursorInContentArea(_GLFWwindow* window)
{ {
int width, height; int width, height;
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
_glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0); _glfwPlatformSetCursorPos(window, width / 2.0, height / 2.0);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW public API ////// ////// GLFW public API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -672,7 +737,9 @@ GLFWAPI void glfwSetInputMode(GLFWwindow* handle, int mode, int value)
window->stickyMouseButtons = value; window->stickyMouseButtons = value;
} }
else if (mode == GLFW_LOCK_KEY_MODS) else if (mode == GLFW_LOCK_KEY_MODS)
{
window->lockKeyMods = value ? true : false; window->lockKeyMods = value ? true : false;
}
else else
_glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode); _glfwInputError(GLFW_INVALID_ENUM, "Invalid input mode 0x%08X", mode);
} }
@@ -685,7 +752,7 @@ GLFWAPI const char* glfwGetKeyName(int key, int scancode)
{ {
if (key != GLFW_KEY_KP_EQUAL && if (key != GLFW_KEY_KP_EQUAL &&
(key < GLFW_KEY_KP_0 || key > GLFW_KEY_KP_ADD) && (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; return NULL;
} }
@@ -1359,15 +1426,17 @@ GLFWAPI int glfwGetGamepadState(int jid, GLFWgamepadstate* state)
const unsigned int bit = e->index & 0xf; const unsigned int bit = e->index & 0xf;
if (js->hats[hat] & bit) if (js->hats[hat] & bit)
state->axes[i] = 1.f; state->axes[i] = 1.f;
else
state->axes[i] = -1.f;
} }
else if (e->type == _GLFW_JOYSTICK_BUTTON) else if (e->type == _GLFW_JOYSTICK_BUTTON)
state->axes[i] = (float) js->buttons[e->index]; state->axes[i] = js->buttons[e->index] * 2.f - 1.f;
} }
return true; return true;
} }
GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string) GLFWAPI void glfwSetClipboardString(GLFWwindow* handle UNUSED, const char* string)
{ {
assert(string != NULL); assert(string != NULL);
@@ -1375,14 +1444,14 @@ GLFWAPI void glfwSetClipboardString(GLFWwindow* handle, const char* string)
_glfwPlatformSetClipboardString(string); _glfwPlatformSetClipboardString(string);
} }
GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle) GLFWAPI const char* glfwGetClipboardString(GLFWwindow* handle UNUSED)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetClipboardString(); return _glfwPlatformGetClipboardString();
} }
#if defined(_GLFW_X11) || defined(_GLFW_WAYLAND) #if defined(_GLFW_X11) || defined(_GLFW_WAYLAND)
GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle, const char* string) GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle UNUSED, const char* string)
{ {
assert(string != NULL); assert(string != NULL);
@@ -1390,7 +1459,7 @@ GLFWAPI void glfwSetPrimarySelectionString(GLFWwindow* handle, const char* strin
_glfwPlatformSetPrimarySelectionString(string); _glfwPlatformSetPrimarySelectionString(string);
} }
GLFWAPI const char* glfwGetPrimarySelectionString(GLFWwindow* handle) GLFWAPI const char* glfwGetPrimarySelectionString(GLFWwindow* handle UNUSED)
{ {
_GLFW_REQUIRE_INIT_OR_RETURN(NULL); _GLFW_REQUIRE_INIT_OR_RETURN(NULL);
return _glfwPlatformGetPrimarySelectionString(); return _glfwPlatformGetPrimarySelectionString();

123
glfw/internal.h vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -225,12 +225,32 @@ typedef void (APIENTRY * PFN_vkVoidFunction)(void);
// Swaps the provided pointers // Swaps the provided pointers
#define _GLFW_SWAP_POINTERS(x, y) \ #define _GLFW_SWAP_POINTERS(x, y) \
{ \ do{ \
void* t; \ __typeof__(x) t; \
t = x; \ t = x; \
x = y; \ x = y; \
y = t; \ y = t; \
} }while(0)
// Suppress some pedantic warnings
#ifdef __clang__
#define START_ALLOW_CASE_RANGE _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wpedantic\"")
#define END_ALLOW_CASE_RANGE _Pragma("clang diagnostic pop")
#define ALLOW_UNUSED_RESULT _Pragma("clang diagnostic push") _Pragma("clang diagnostic ignored \"-Wunused-result\"")
#define END_ALLOW_UNUSED_RESULT _Pragma("clang diagnostic pop")
#else
#define START_ALLOW_CASE_RANGE _Pragma("GCC diagnostic ignored \"-Wpedantic\"")
#define END_ALLOW_CASE_RANGE _Pragma("GCC diagnostic pop")
#define ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic ignored \"-Wunused-result\"")
#define END_ALLOW_UNUSED_RESULT _Pragma("GCC diagnostic pop")
#endif
// dlsym that works with -Wpedantic
#define glfw_dlsym(dest, handle, name) do {*(void **)&(dest) = _glfw_dlsym(handle, name);}while (0)
// Mark function arguments as unused
#define UNUSED __attribute__ ((unused))
// Per-thread error structure // Per-thread error structure
// //
@@ -247,12 +267,12 @@ struct _GLFWerror
// //
struct _GLFWinitconfig struct _GLFWinitconfig
{ {
bool hatButtons; bool hatButtons;
bool debugKeyboard; bool debugKeyboard;
bool enableJoysticks; bool enableJoysticks;
struct { struct {
bool menubar; bool menubar;
bool chdir; bool chdir;
} ns; } ns;
}; };
@@ -267,18 +287,18 @@ struct _GLFWwndconfig
int width; int width;
int height; int height;
const char* title; const char* title;
bool resizable; bool resizable;
bool visible; bool visible;
bool decorated; bool decorated;
bool focused; bool focused;
bool autoIconify; bool autoIconify;
bool floating; bool floating;
bool maximized; bool maximized;
bool centerCursor; bool centerCursor;
bool focusOnShow; bool focusOnShow;
bool scaleToMonitor; bool scaleToMonitor;
struct { struct {
bool retina; bool retina;
char frameName[256]; char frameName[256];
} ns; } ns;
struct { struct {
@@ -302,15 +322,15 @@ struct _GLFWctxconfig
int source; int source;
int major; int major;
int minor; int minor;
bool forward; bool forward;
bool debug; bool debug;
bool noerror; bool noerror;
int profile; int profile;
int robustness; int robustness;
int release; int release;
_GLFWwindow* share; _GLFWwindow* share;
struct { struct {
bool offline; bool offline;
} nsgl; } nsgl;
}; };
@@ -335,11 +355,11 @@ struct _GLFWfbconfig
int accumBlueBits; int accumBlueBits;
int accumAlphaBits; int accumAlphaBits;
int auxBuffers; int auxBuffers;
bool stereo; bool stereo;
int samples; int samples;
bool sRGB; bool sRGB;
bool doublebuffer; bool doublebuffer;
bool transparent; bool transparent;
uintptr_t handle; uintptr_t handle;
}; };
@@ -350,7 +370,7 @@ struct _GLFWcontext
int client; int client;
int source; int source;
int major, minor, revision; int major, minor, revision;
bool forward, debug, noerror; bool forward, debug, noerror;
int profile; int profile;
int robustness; int robustness;
int release; int release;
@@ -367,7 +387,7 @@ struct _GLFWcontext
_GLFWdestroycontextfun destroy; _GLFWdestroycontextfun destroy;
// This is defined in the context API's context.h // This is defined in the context API's context.h
_GLFW_PLATFORM_CONTEXT_STATE; _GLFW_PLATFORM_CONTEXT_STATE
// This is defined in egl_context.h // This is defined in egl_context.h
_GLFW_EGL_CONTEXT_STATE; _GLFW_EGL_CONTEXT_STATE;
// This is defined in osmesa_context.h // This is defined in osmesa_context.h
@@ -381,12 +401,12 @@ struct _GLFWwindow
struct _GLFWwindow* next; struct _GLFWwindow* next;
// Window settings and state // Window settings and state
bool resizable; bool resizable;
bool decorated; bool decorated;
bool autoIconify; bool autoIconify;
bool floating; bool floating;
bool focusOnShow; bool focusOnShow;
bool shouldClose; bool shouldClose;
void* userPointer; void* userPointer;
GLFWid id; GLFWid id;
GLFWvidmode videoMode; GLFWvidmode videoMode;
@@ -397,9 +417,9 @@ struct _GLFWwindow
int maxwidth, maxheight; int maxwidth, maxheight;
int numer, denom; int numer, denom;
bool stickyKeys; bool stickyKeys;
bool stickyMouseButtons; bool stickyMouseButtons;
bool lockKeyMods; bool lockKeyMods;
int cursorMode; int cursorMode;
char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1]; char mouseButtons[GLFW_MOUSE_BUTTON_LAST + 1];
char keys[GLFW_KEY_LAST + 1]; char keys[GLFW_KEY_LAST + 1];
@@ -490,7 +510,7 @@ struct _GLFWmapping
// //
struct _GLFWjoystick struct _GLFWjoystick
{ {
bool present; bool present;
float* axes; float* axes;
int axisCount; int axisCount;
unsigned char* buttons; unsigned char* buttons;
@@ -526,7 +546,7 @@ struct _GLFWmutex
// //
struct _GLFWlibrary struct _GLFWlibrary
{ {
bool initialized; bool initialized;
struct { struct {
_GLFWinitconfig init; _GLFWinitconfig init;
@@ -559,23 +579,23 @@ struct _GLFWlibrary
} timer; } timer;
struct { struct {
bool available; bool available;
void* handle; void* handle;
char* extensions[2]; char* extensions[2];
#if !defined(_GLFW_VULKAN_STATIC) #if !defined(_GLFW_VULKAN_STATIC)
PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties; PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties;
PFN_vkGetInstanceProcAddr GetInstanceProcAddr; PFN_vkGetInstanceProcAddr GetInstanceProcAddr;
#endif #endif
bool KHR_surface; bool KHR_surface;
#if defined(_GLFW_WIN32) #if defined(_GLFW_WIN32)
bool KHR_win32_surface; bool KHR_win32_surface;
#elif defined(_GLFW_COCOA) #elif defined(_GLFW_COCOA)
bool MVK_macos_surface; bool MVK_macos_surface;
#elif defined(_GLFW_X11) #elif defined(_GLFW_X11)
bool KHR_xlib_surface; bool KHR_xlib_surface;
bool KHR_xcb_surface; bool KHR_xcb_surface;
#elif defined(_GLFW_WAYLAND) #elif defined(_GLFW_WAYLAND)
bool KHR_wayland_surface; bool KHR_wayland_surface;
#endif #endif
} vk; } vk;
@@ -587,9 +607,9 @@ struct _GLFWlibrary
// This is defined in the window API's platform.h // This is defined in the window API's platform.h
_GLFW_PLATFORM_LIBRARY_WINDOW_STATE; _GLFW_PLATFORM_LIBRARY_WINDOW_STATE;
// This is defined in the context API's context.h // This is defined in the context API's context.h
_GLFW_PLATFORM_LIBRARY_CONTEXT_STATE; _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE
// This is defined in the platform's joystick.h // This is defined in the platform's joystick.h
_GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE; _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE
// This is defined in egl_context.h // This is defined in egl_context.h
_GLFW_EGL_LIBRARY_CONTEXT_STATE; _GLFW_EGL_LIBRARY_CONTEXT_STATE;
// This is defined in osmesa_context.h // This is defined in osmesa_context.h
@@ -802,7 +822,6 @@ const char* _glfwGetVulkanResultString(VkResult result);
_GLFWwindow* _glfwFocusedWindow(void); _GLFWwindow* _glfwFocusedWindow(void);
_GLFWwindow* _glfwWindowForId(GLFWid id); _GLFWwindow* _glfwWindowForId(GLFWid id);
void _glfwPlatformRunMainLoop(GLFWtickcallback, void*); void _glfwPlatformRunMainLoop(GLFWtickcallback, void*);
void _glfwPlatformRequestTickCallback(void);
void _glfwPlatformStopMainLoop(void); void _glfwPlatformStopMainLoop(void);
unsigned long long _glfwPlatformAddTimer(double interval, bool repeats, GLFWuserdatafun callback, void *callback_data, GLFWuserdatafun free_callback); 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); void _glfwPlatformUpdateTimer(unsigned long long timer_id, double interval, bool enabled);

71
glfw/linux_joystick.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 Linux - www.glfw.org // GLFW 3.4 Linux - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -104,9 +106,7 @@ static void handleAbsEvent(_GLFWjoystick* js, int code, int value)
// //
static void pollAbsState(_GLFWjoystick* js) static void pollAbsState(_GLFWjoystick* js)
{ {
int code; for (int code = 0; code < ABS_CNT; code++)
for (code = 0; code < ABS_CNT; code++)
{ {
if (js->linjs.absMap[code] < 0) if (js->linjs.absMap[code] < 0)
continue; continue;
@@ -126,18 +126,7 @@ static void pollAbsState(_GLFWjoystick* js)
// //
static bool openJoystickDevice(const char* path) static bool openJoystickDevice(const char* path)
{ {
int jid, code; for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
char name[256] = "";
char guid[33] = "";
char evBits[(EV_CNT + 7) / 8] = {0};
char keyBits[(KEY_CNT + 7) / 8] = {0};
char absBits[(ABS_CNT + 7) / 8] = {0};
int axisCount = 0, buttonCount = 0, hatCount = 0;
struct input_id id;
_GLFWjoystickLinux linjs = {0};
_GLFWjoystick* js = NULL;
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (!_glfw.joysticks[jid].present) if (!_glfw.joysticks[jid].present)
continue; continue;
@@ -145,14 +134,20 @@ static bool openJoystickDevice(const char* path)
return false; return false;
} }
_GLFWjoystickLinux linjs = {0};
linjs.fd = open(path, O_RDONLY | O_NONBLOCK); linjs.fd = open(path, O_RDONLY | O_NONBLOCK);
if (linjs.fd == -1) if (linjs.fd == -1)
return false; return false;
if (ioctl(linjs.fd, EVIOCGBIT(0, sizeof(evBits)), evBits) < 0 || char evBits[(EV_CNT + 7) / 8] = {0};
ioctl(linjs.fd, EVIOCGBIT(EV_KEY, sizeof(keyBits)), keyBits) < 0 || char keyBits[(KEY_CNT + 7) / 8] = {0};
ioctl(linjs.fd, EVIOCGBIT(EV_ABS, sizeof(absBits)), absBits) < 0 || char absBits[(ABS_CNT + 7) / 8] = {0};
ioctl(linjs.fd, EVIOCGID, &id) < 0) struct input_id id;
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, _glfwInputError(GLFW_PLATFORM_ERROR,
"Linux: Failed to query input device: %s", "Linux: Failed to query input device: %s",
@@ -168,9 +163,13 @@ static bool openJoystickDevice(const char* path)
return false; return false;
} }
if (ioctl(linjs.fd, EVIOCGNAME(sizeof(name)), name) < 0) char name[256] = "";
if (ioctl(linjs.fd, (int32_t)EVIOCGNAME(sizeof(name)), name) < 0)
strncpy(name, "Unknown", sizeof(name)); strncpy(name, "Unknown", sizeof(name));
char guid[33] = "";
// Generate a joystick GUID that matches the SDL 2.0.5+ one // Generate a joystick GUID that matches the SDL 2.0.5+ one
if (id.vendor && id.product && id.version) if (id.vendor && id.product && id.version)
{ {
@@ -189,7 +188,9 @@ static bool openJoystickDevice(const char* path)
name[8], name[9], name[10]); name[8], name[9], name[10]);
} }
for (code = BTN_MISC; code < KEY_CNT; code++) int axisCount = 0, buttonCount = 0, hatCount = 0;
for (int code = BTN_MISC; code < KEY_CNT; code++)
{ {
if (!isBitSet(code, keyBits)) if (!isBitSet(code, keyBits))
continue; continue;
@@ -198,7 +199,7 @@ static bool openJoystickDevice(const char* path)
buttonCount++; buttonCount++;
} }
for (code = 0; code < ABS_CNT; code++) for (int code = 0; code < ABS_CNT; code++)
{ {
linjs.absMap[code] = -1; linjs.absMap[code] = -1;
if (!isBitSet(code, absBits)) if (!isBitSet(code, absBits))
@@ -221,7 +222,7 @@ static bool openJoystickDevice(const char* path)
} }
} }
js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount); _GLFWjoystick* js = _glfwAllocJoystick(name, guid, axisCount, buttonCount, hatCount);
if (!js) if (!js)
{ {
close(linjs.fd); close(linjs.fd);
@@ -266,8 +267,6 @@ static int compareJoysticks(const void* fp, const void* sp)
// //
bool _glfwInitJoysticksLinux(void) bool _glfwInitJoysticksLinux(void)
{ {
DIR* dir;
int count = 0;
const char* dirname = "/dev/input"; const char* dirname = "/dev/input";
_glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC); _glfw.linjs.inotify = inotify_init1(IN_NONBLOCK | IN_CLOEXEC);
@@ -289,7 +288,9 @@ bool _glfwInitJoysticksLinux(void)
return false; return false;
} }
dir = opendir(dirname); int count = 0;
DIR* dir = opendir(dirname);
if (dir) if (dir)
{ {
struct dirent* entry; struct dirent* entry;
@@ -314,7 +315,7 @@ bool _glfwInitJoysticksLinux(void)
// Continue with no joysticks if enumeration fails // Continue with no joysticks if enumeration fails
qsort(_glfw.joysticks, count, sizeof(_GLFWjoystick), compareJoysticks); qsort(_glfw.joysticks, count, sizeof(_glfw.joysticks[0]), compareJoysticks);
return true; return true;
} }
@@ -344,12 +345,12 @@ void _glfwTerminateJoysticksLinux(void)
void _glfwDetectJoystickConnectionLinux(void) void _glfwDetectJoystickConnectionLinux(void)
{ {
ssize_t offset = 0;
char buffer[16384];
if (_glfw.linjs.inotify <= 0) if (_glfw.linjs.inotify <= 0)
return; return;
ssize_t offset = 0;
char buffer[16384];
const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer)); const ssize_t size = read(_glfw.linjs.inotify, buffer, sizeof(buffer));
while (size > offset) while (size > offset)
@@ -369,9 +370,7 @@ void _glfwDetectJoystickConnectionLinux(void)
openJoystickDevice(path); openJoystickDevice(path);
else if (e->mask & IN_DELETE) else if (e->mask & IN_DELETE)
{ {
int jid; for (int jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
for (jid = 0; jid <= GLFW_JOYSTICK_LAST; jid++)
{ {
if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0) if (strcmp(_glfw.joysticks[jid].linjs.path, path) == 0)
{ {
@@ -388,7 +387,7 @@ void _glfwDetectJoystickConnectionLinux(void)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode UNUSED)
{ {
// Read all queued events (non-blocking) // Read all queued events (non-blocking)
for (;;) for (;;)
@@ -428,6 +427,6 @@ int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode)
return js->present; return js->present;
} }
void _glfwPlatformUpdateGamepadGUID(char* guid) void _glfwPlatformUpdateGamepadGUID(char* guid UNUSED)
{ {
} }

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> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@@ -29,7 +29,7 @@
#include <regex.h> #include <regex.h>
#define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs #define _GLFW_PLATFORM_JOYSTICK_STATE _GLFWjoystickLinux linjs
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE _GLFWlibraryLinux linjs;
#define _GLFW_PLATFORM_MAPPING_NAME "Linux" #define _GLFW_PLATFORM_MAPPING_NAME "Linux"
@@ -52,11 +52,10 @@ typedef struct _GLFWlibraryLinux
int inotify; int inotify;
int watch; int watch;
regex_t regex; regex_t regex;
bool dropped; bool dropped;
} _GLFWlibraryLinux; } _GLFWlibraryLinux;
bool _glfwInitJoysticksLinux(void); bool _glfwInitJoysticksLinux(void);
void _glfwTerminateJoysticksLinux(void); void _glfwTerminateJoysticksLinux(void);
void _glfwDetectJoystickConnectionLinux(void); void _glfwDetectJoystickConnectionLinux(void);

3
glfw/linux_notify.c vendored
View File

@@ -43,8 +43,7 @@ notification_created(DBusMessage *msg, const char* errmsg, void *data) {
} }
static DBusHandlerResult static DBusHandlerResult
message_handler(DBusConnection *conn, DBusMessage *msg, void *user_data) { message_handler(DBusConnection *conn UNUSED, DBusMessage *msg, void *user_data UNUSED) {
(void)(user_data);
/* printf("session_bus message_handler invoked interface: %s member: %s\n", dbus_message_get_interface(msg), dbus_message_get_member(msg)); */ /* printf("session_bus message_handler invoked interface: %s member: %s\n", dbus_message_get_interface(msg), dbus_message_get_member(msg)); */
if (dbus_message_is_signal(msg, NOTIFICATIONS_IFACE, "ActionInvoked")) { if (dbus_message_is_signal(msg, NOTIFICATIONS_IFACE, "ActionInvoked")) {
uint32_t notification_id; uint32_t notification_id;

13
glfw/main_loop.h vendored
View File

@@ -14,8 +14,6 @@
static bool keep_going = false; static bool keep_going = false;
void _glfwPlatformRequestTickCallback() {
}
void _glfwPlatformStopMainLoop(void) { void _glfwPlatformStopMainLoop(void) {
if (keep_going) { if (keep_going) {
@@ -25,12 +23,17 @@ void _glfwPlatformStopMainLoop(void) {
} }
void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) { void _glfwPlatformRunMainLoop(GLFWtickcallback tick_callback, void* data) {
keep_going = true; keep_going = 1;
EventLoopData *eld = &_glfw.GLFW_LOOP_BACKEND.eventLoopData;
while(keep_going) { while(keep_going) {
_glfwPlatformWaitEvents(); _glfwPlatformWaitEvents();
EVDBG("loop tick"); EVDBG("--------- loop tick, wakeups_happened: %d ----------", eld->wakeup_data_read);
tick_callback(data); if (eld->wakeup_data_read) {
eld->wakeup_data_read = false;
tick_callback(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(double interval, bool repeats, GLFWuserdatafreefun callback, void *callback_data, GLFWuserdatafreefun free_callback) {

4
glfw/mappings.h vendored
View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages

25
glfw/monitor.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@@ -54,6 +56,10 @@ static int compareVideoModes(const void* fp, const void* sp)
if (farea != sarea) if (farea != sarea)
return farea - sarea; return farea - sarea;
// Then sort on width
if (fm->width != sm->width)
return fm->width - sm->width;
// Lastly sort on refresh rate // Lastly sort on refresh rate
return fm->refreshRate - sm->refreshRate; return fm->refreshRate - sm->refreshRate;
} }
@@ -72,7 +78,7 @@ static bool refreshVideoModes(_GLFWmonitor* monitor)
if (!modes) if (!modes)
return false; return false;
qsort(modes, modeCount, sizeof(GLFWvidmode), compareVideoModes); qsort(modes, modeCount, sizeof(modes[0]), compareVideoModes);
free(monitor->modes); free(monitor->modes);
monitor->modes = modes; monitor->modes = modes;
@@ -100,7 +106,7 @@ void _glfwInputMonitor(_GLFWmonitor* monitor, int action, int placement)
{ {
memmove(_glfw.monitors + 1, memmove(_glfw.monitors + 1,
_glfw.monitors, _glfw.monitors,
(_glfw.monitorCount - 1) * sizeof(_GLFWmonitor*)); ((size_t) _glfw.monitorCount - 1) * sizeof(_GLFWmonitor*));
_glfw.monitors[0] = monitor; _glfw.monitors[0] = monitor;
} }
else else
@@ -327,7 +333,9 @@ GLFWAPI void glfwGetMonitorPos(GLFWmonitor* handle, int* xpos, int* ypos)
_glfwPlatformGetMonitorPos(monitor, xpos, ypos); _glfwPlatformGetMonitorPos(monitor, xpos, ypos);
} }
GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle, int* xpos, int* ypos, int* width, int* height) GLFWAPI void glfwGetMonitorWorkarea(GLFWmonitor* handle,
int* xpos, int* ypos,
int* width, int* height)
{ {
_GLFWmonitor* monitor = (_GLFWmonitor*) handle; _GLFWmonitor* monitor = (_GLFWmonitor*) handle;
assert(monitor != NULL); assert(monitor != NULL);
@@ -448,7 +456,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
GLFWgammaramp ramp; GLFWgammaramp ramp;
const GLFWgammaramp* original; const GLFWgammaramp* original;
assert(handle != NULL); assert(handle != NULL);
assert(gamma >= 0.f); assert(gamma > 0.f);
assert(gamma <= FLT_MAX); assert(gamma <= FLT_MAX);
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
@@ -458,6 +466,7 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
_glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma); _glfwInputError(GLFW_INVALID_VALUE, "Invalid gamma value %f", gamma);
return; return;
} }
original = glfwGetGammaRamp(handle); original = glfwGetGammaRamp(handle);
if (!original) if (!original)
return; return;
@@ -472,10 +481,8 @@ GLFWAPI void glfwSetGamma(GLFWmonitor* handle, float gamma)
value = i / (float) (original->size - 1); value = i / (float) (original->size - 1);
// Apply gamma curve // Apply gamma curve
value = powf(value, 1.f / gamma) * 65535.f + 0.5f; value = powf(value, 1.f / gamma) * 65535.f + 0.5f;
// Clamp to value range // Clamp to value range
if (value > 65535.f) value = fminf(value, 65535.f);
value = 65535.f;
values[i] = (unsigned short) value; values[i] = (unsigned short) value;
} }

9
glfw/nsgl_context.h vendored
View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 macOS - www.glfw.org // GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,8 +24,8 @@
// //
//======================================================================== //========================================================================
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl #define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextNSGL nsgl;
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl #define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryNSGL nsgl;
// NSGL-specific per-context data // NSGL-specific per-context data
@@ -53,4 +53,3 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig, const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig); const _GLFWfbconfig* fbconfig);
void _glfwDestroyContextNSGL(_GLFWwindow* window); void _glfwDestroyContextNSGL(_GLFWwindow* window);

View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 macOS - www.glfw.org // GLFW 3.4 macOS - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2009-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2009-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -23,6 +23,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -43,15 +45,14 @@ static void swapBuffersNSGL(_GLFWwindow* window)
[window->context.nsgl.object flushBuffer]; [window->context.nsgl.object flushBuffer];
} }
static void swapIntervalNSGL(int interval) static void swapIntervalNSGL(int interval UNUSED)
{ {
// As of Mojave this does not work so we use CVDisplayLink instead // As of Mojave this does not work so we use CVDisplayLink instead
(void)(interval);
_glfwInputError(GLFW_API_UNAVAILABLE, _glfwInputError(GLFW_API_UNAVAILABLE,
"NSGL: Swap intervals do not work on macOS"); "NSGL: Swap intervals do not work on macOS");
} }
static int extensionSupportedNSGL(const char* extension) static int extensionSupportedNSGL(const char* extension UNUSED)
{ {
// There are no NSGL extensions // There are no NSGL extensions
return false; return false;
@@ -63,8 +64,9 @@ static GLFWglproc getProcAddressNSGL(const char* procname)
procname, procname,
kCFStringEncodingASCII); kCFStringEncodingASCII);
GLFWglproc symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework, GLFWglproc symbol;
symbolName); *(void **) &symbol = CFBundleGetFunctionPointerForName(_glfw.nsgl.framework,
symbolName);
CFRelease(symbolName); CFRelease(symbolName);
@@ -131,7 +133,6 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
"NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above"); "NSGL: The targeted version of macOS does not support OpenGL 3.0 or 3.1 but may support 3.2 and above");
return false; return false;
} }
} }
// Context robustness modes (GL_KHR_robustness) are not yet supported by // Context robustness modes (GL_KHR_robustness) are not yet supported by
@@ -288,7 +289,8 @@ bool _glfwCreateContextNSGL(_GLFWwindow* window,
if (fbconfig->transparent) if (fbconfig->transparent)
{ {
GLint opaque = 0; GLint opaque = 0;
[window->context.nsgl.object setValues:&opaque forParameter:NSOpenGLContextParameterSurfaceOpacity]; [window->context.nsgl.object setValues:&opaque
forParameter:NSOpenGLContextParameterSurfaceOpacity];
} }
if (window->ns.retina) if (window->ns.retina)

6
glfw/null_init.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"

10
glfw/null_joystick.c vendored
View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -23,6 +23,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -31,12 +33,12 @@
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
int _glfwPlatformPollJoystick(_GLFWjoystick* js, int mode) int _glfwPlatformPollJoystick(_GLFWjoystick* js UNUSED, int mode UNUSED)
{ {
return false; return false;
} }
void _glfwPlatformUpdateGamepadGUID(char* guid) void _glfwPlatformUpdateGamepadGUID(char* guid UNUSED)
{ {
} }

View File

@@ -1,7 +1,7 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -25,7 +25,6 @@
//======================================================================== //========================================================================
#define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs #define _GLFW_PLATFORM_JOYSTICK_STATE int nulljs
#define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs #define _GLFW_PLATFORM_LIBRARY_JOYSTICK_STATE int nulljs;
#define _GLFW_PLATFORM_MAPPING_NAME "" #define _GLFW_PLATFORM_MAPPING_NAME ""

25
glfw/null_monitor.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -32,15 +34,15 @@
////// GLFW platform API ////// ////// 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) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
@@ -49,24 +51,27 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
*yscale = 1.f; *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; 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; return false;
} }
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED, const GLFWgammaramp* ramp UNUSED)
{ {
} }

View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages

129
glfw/null_window.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -76,28 +78,28 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
window->context.destroy(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, void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED, int count UNUSED,
const GLFWimage* images) const GLFWimage* images UNUSED)
{ {
} }
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window UNUSED,
_GLFWmonitor* monitor, _GLFWmonitor* monitor UNUSED,
int xpos, int ypos, int xpos UNUSED, int ypos UNUSED,
int width, int height, int width UNUSED, int height UNUSED,
int refreshRate) 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)
{ {
} }
@@ -115,13 +117,13 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
window->null.height = height; window->null.height = height;
} }
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window UNUSED,
int minwidth, int minheight, int minwidth UNUSED, int minheight UNUSED,
int maxwidth, int maxheight) 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)
{ {
} }
@@ -133,13 +135,13 @@ void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* heigh
*height = window->null.height; *height = window->null.height;
} }
void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window, void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window UNUSED,
int* left, int* top, int* left UNUSED, int* top UNUSED,
int* right, int* bottom) int* right UNUSED, int* bottom UNUSED)
{ {
} }
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
@@ -148,101 +150,101 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
*yscale = 1.f; *yscale = 1.f;
} }
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window) double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
{ {
return 0.5; return 0.5;
} }
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; return false;
} }
int _glfwPlatformWindowHovered(_GLFWwindow* window) int _glfwPlatformWindowHovered(_GLFWwindow* window UNUSED)
{ {
return false; return false;
} }
int _glfwPlatformFramebufferTransparent(_GLFWwindow* window) int _glfwPlatformFramebufferTransparent(_GLFWwindow* window UNUSED)
{ {
return false; 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; 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; 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; return false;
} }
int _glfwPlatformWindowOccluded(_GLFWwindow* window) int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
{ {
return false; return false;
} }
int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window UNUSED)
{ {
return false; return false;
} }
int _glfwPlatformWindowVisible(_GLFWwindow* window) int _glfwPlatformWindowVisible(_GLFWwindow* window UNUSED)
{ {
return false; return false;
} }
@@ -255,7 +257,7 @@ void _glfwPlatformWaitEvents(void)
{ {
} }
void _glfwPlatformWaitEventsTimeout(double timeout) void _glfwPlatformWaitEventsTimeout(double timeout UNUSED)
{ {
} }
@@ -263,39 +265,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, int _glfwPlatformCreateCursor(_GLFWcursor* cursor UNUSED,
const GLFWimage* image, const GLFWimage* image UNUSED,
int xhot, int yhot, int count) int xhot UNUSED, int yhot UNUSED, int count UNUSED)
{ {
return true; return true;
} }
int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor, int shape) int _glfwPlatformCreateStandardCursor(_GLFWcursor* cursor UNUSED, int shape UNUSED)
{ {
return true; 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)
{ {
} }
@@ -304,32 +306,33 @@ const char* _glfwPlatformGetClipboardString(void)
return NULL; return NULL;
} }
const char* _glfwPlatformGetScancodeName(int scancode) const char* _glfwPlatformGetScancodeName(int scancode UNUSED)
{ {
return ""; return "";
} }
int _glfwPlatformGetKeyScancode(int key) int _glfwPlatformGetKeyScancode(int key UNUSED)
{ {
return -1; return -1;
} }
void _glfwPlatformGetRequiredInstanceExtensions(char** extensions) void _glfwPlatformGetRequiredInstanceExtensions(char** extensions UNUSED)
{ {
} }
int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance, int _glfwPlatformGetPhysicalDevicePresentationSupport(VkInstance instance UNUSED,
VkPhysicalDevice device, VkPhysicalDevice device UNUSED,
uint32_t queuefamily) uint32_t queuefamily UNUSED)
{ {
return false; return false;
} }
VkResult _glfwPlatformCreateWindowSurface(VkInstance instance, VkResult _glfwPlatformCreateWindowSurface(VkInstance instance UNUSED,
_GLFWwindow* window, _GLFWwindow* window UNUSED,
const VkAllocationCallbacks* allocator, const VkAllocationCallbacks* allocator UNUSED,
VkSurfaceKHR* surface) VkSurfaceKHR* surface UNUSED)
{ {
// This seems like the most appropriate error to return here // This seems like the most appropriate error to return here
return VK_ERROR_INITIALIZATION_FAILED; return VK_ERROR_INITIALIZATION_FAILED;
} }

37
glfw/osmesa_context.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 OSMesa - www.glfw.org // GLFW 3.4 OSMesa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -47,7 +49,7 @@ static void makeContextCurrentOSMesa(_GLFWwindow* window)
free(window->context.osmesa.buffer); free(window->context.osmesa.buffer);
// Allocate the new buffer (width * height * 8-bit RGBA) // Allocate the new buffer (width * height * 8-bit RGBA)
window->context.osmesa.buffer = calloc(4, width * height); window->context.osmesa.buffer = calloc(4, (size_t) width * height);
window->context.osmesa.width = width; window->context.osmesa.width = width;
window->context.osmesa.height = height; window->context.osmesa.height = height;
} }
@@ -87,17 +89,17 @@ static void destroyContextOSMesa(_GLFWwindow* window)
} }
} }
static void swapBuffersOSMesa(_GLFWwindow* window) static void swapBuffersOSMesa(_GLFWwindow* window UNUSED)
{ {
// No double buffering on OSMesa // No double buffering on OSMesa
} }
static void swapIntervalOSMesa(int interval) static void swapIntervalOSMesa(int interval UNUSED)
{ {
// No swap interval on OSMesa // No swap interval on OSMesa
} }
static int extensionSupportedOSMesa(const char* extension) static int extensionSupportedOSMesa(const char* extension UNUSED)
{ {
// OSMesa does not have extensions // OSMesa does not have extensions
return false; return false;
@@ -145,20 +147,13 @@ bool _glfwInitOSMesa(void)
return false; return false;
} }
_glfw.osmesa.CreateContextExt = (PFN_OSMesaCreateContextExt) glfw_dlsym(_glfw.osmesa.CreateContextExt, _glfw.osmesa.handle, "OSMesaCreateContextExt");
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextExt"); glfw_dlsym(_glfw.osmesa.CreateContextAttribs, _glfw.osmesa.handle, "OSMesaCreateContextAttribs");
_glfw.osmesa.CreateContextAttribs = (PFN_OSMesaCreateContextAttribs) glfw_dlsym(_glfw.osmesa.DestroyContext, _glfw.osmesa.handle, "OSMesaDestroyContext");
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaCreateContextAttribs"); glfw_dlsym(_glfw.osmesa.MakeCurrent, _glfw.osmesa.handle, "OSMesaMakeCurrent");
_glfw.osmesa.DestroyContext = (PFN_OSMesaDestroyContext) glfw_dlsym(_glfw.osmesa.GetColorBuffer, _glfw.osmesa.handle, "OSMesaGetColorBuffer");
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaDestroyContext"); glfw_dlsym(_glfw.osmesa.GetDepthBuffer, _glfw.osmesa.handle, "OSMesaGetDepthBuffer");
_glfw.osmesa.MakeCurrent = (PFN_OSMesaMakeCurrent) glfw_dlsym(_glfw.osmesa.GetProcAddress, _glfw.osmesa.handle, "OSMesaGetProcAddress");
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaMakeCurrent");
_glfw.osmesa.GetColorBuffer = (PFN_OSMesaGetColorBuffer)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetColorBuffer");
_glfw.osmesa.GetDepthBuffer = (PFN_OSMesaGetDepthBuffer)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetDepthBuffer");
_glfw.osmesa.GetProcAddress = (PFN_OSMesaGetProcAddress)
_glfw_dlsym(_glfw.osmesa.handle, "OSMesaGetProcAddress");
if (!_glfw.osmesa.CreateContextExt || if (!_glfw.osmesa.CreateContextExt ||
!_glfw.osmesa.DestroyContext || !_glfw.osmesa.DestroyContext ||
@@ -188,7 +183,7 @@ void _glfwTerminateOSMesa(void)
#define setAttrib(a, v) \ #define setAttrib(a, v) \
{ \ { \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \ assert(((size_t) index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \ attribs[index++] = a; \
attribs[index++] = v; \ attribs[index++] = v; \
} }

View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 OSMesa - www.glfw.org // GLFW 3.4 OSMesa - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2016 Google Inc. // Copyright (c) 2016 Google Inc.
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2016-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages

6
glfw/posix_thread.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 POSIX - www.glfw.org // GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"

8
glfw/posix_thread.h vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 POSIX - www.glfw.org // GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -35,7 +35,7 @@
// //
typedef struct _GLFWtlsPOSIX typedef struct _GLFWtlsPOSIX
{ {
bool allocated; bool allocated;
pthread_key_t key; pthread_key_t key;
} _GLFWtlsPOSIX; } _GLFWtlsPOSIX;
@@ -44,7 +44,7 @@ typedef struct _GLFWtlsPOSIX
// //
typedef struct _GLFWmutexPOSIX typedef struct _GLFWmutexPOSIX
{ {
bool allocated; bool allocated;
pthread_mutex_t handle; pthread_mutex_t handle;
} _GLFWmutexPOSIX; } _GLFWmutexPOSIX;

6
glfw/posix_time.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 POSIX - www.glfw.org // GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"

6
glfw/posix_time.h vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 POSIX - www.glfw.org // GLFW 3.4 POSIX - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2017 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -34,7 +34,7 @@
// //
typedef struct _GLFWtimerPOSIX typedef struct _GLFWtimerPOSIX
{ {
bool monotonic; bool monotonic;
uint64_t frequency; uint64_t frequency;
} _GLFWtimerPOSIX; } _GLFWtimerPOSIX;

10
glfw/vulkan.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2018 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@@ -66,7 +68,7 @@ bool _glfwInitVulkan(int mode)
return false; return false;
} }
_glfw.vk.GetInstanceProcAddr = (PFN_vkGetInstanceProcAddr) *(void **) &_glfw.vk.GetInstanceProcAddr =
_glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr"); _glfw_dlsym(_glfw.vk.handle, "vkGetInstanceProcAddr");
if (!_glfw.vk.GetInstanceProcAddr) if (!_glfw.vk.GetInstanceProcAddr)
{ {
@@ -260,7 +262,7 @@ GLFWAPI GLFWvkproc glfwGetInstanceProcAddress(VkInstance instance,
} }
#else #else
if (!proc) if (!proc)
proc = (GLFWvkproc) _glfw_dlsym(_glfw.vk.handle, procname); *(void **) &proc = _glfw_dlsym(_glfw.vk.handle, procname);
#endif #endif
return proc; return proc;

743
glfw/wgl_context.c vendored
View File

@@ -1,743 +0,0 @@
//========================================================================
// GLFW 3.3 WGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-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.
//
//========================================================================
#include "internal.h"
#include <stdlib.h>
#include <malloc.h>
#include <assert.h>
// Returns the specified attribute of the specified pixel format
//
static int getPixelFormatAttrib(_GLFWwindow* window, int pixelFormat, int attrib)
{
int value = 0;
assert(_glfw.wgl.ARB_pixel_format);
if (!_glfw.wgl.GetPixelFormatAttribivARB(window->context.wgl.dc,
pixelFormat,
0, 1, &attrib, &value))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve pixel format attribute");
return 0;
}
return value;
}
// Return a list of available and usable framebuffer configs
//
static int choosePixelFormat(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
_GLFWfbconfig* usableConfigs;
const _GLFWfbconfig* closest;
int i, pixelFormat, nativeCount, usableCount;
if (_glfw.wgl.ARB_pixel_format)
{
nativeCount = getPixelFormatAttrib(window,
1,
WGL_NUMBER_PIXEL_FORMATS_ARB);
}
else
{
nativeCount = DescribePixelFormat(window->context.wgl.dc,
1,
sizeof(PIXELFORMATDESCRIPTOR),
NULL);
}
usableConfigs = calloc(nativeCount, sizeof(_GLFWfbconfig));
usableCount = 0;
for (i = 0; i < nativeCount; i++)
{
const int n = i + 1;
_GLFWfbconfig* u = usableConfigs + usableCount;
if (_glfw.wgl.ARB_pixel_format)
{
// Get pixel format attributes through "modern" extension
if (!getPixelFormatAttrib(window, n, WGL_SUPPORT_OPENGL_ARB) ||
!getPixelFormatAttrib(window, n, WGL_DRAW_TO_WINDOW_ARB))
{
continue;
}
if (getPixelFormatAttrib(window, n, WGL_PIXEL_TYPE_ARB) !=
WGL_TYPE_RGBA_ARB)
{
continue;
}
if (getPixelFormatAttrib(window, n, WGL_ACCELERATION_ARB) ==
WGL_NO_ACCELERATION_ARB)
{
continue;
}
u->redBits = getPixelFormatAttrib(window, n, WGL_RED_BITS_ARB);
u->greenBits = getPixelFormatAttrib(window, n, WGL_GREEN_BITS_ARB);
u->blueBits = getPixelFormatAttrib(window, n, WGL_BLUE_BITS_ARB);
u->alphaBits = getPixelFormatAttrib(window, n, WGL_ALPHA_BITS_ARB);
u->depthBits = getPixelFormatAttrib(window, n, WGL_DEPTH_BITS_ARB);
u->stencilBits = getPixelFormatAttrib(window, n, WGL_STENCIL_BITS_ARB);
u->accumRedBits = getPixelFormatAttrib(window, n, WGL_ACCUM_RED_BITS_ARB);
u->accumGreenBits = getPixelFormatAttrib(window, n, WGL_ACCUM_GREEN_BITS_ARB);
u->accumBlueBits = getPixelFormatAttrib(window, n, WGL_ACCUM_BLUE_BITS_ARB);
u->accumAlphaBits = getPixelFormatAttrib(window, n, WGL_ACCUM_ALPHA_BITS_ARB);
u->auxBuffers = getPixelFormatAttrib(window, n, WGL_AUX_BUFFERS_ARB);
if (getPixelFormatAttrib(window, n, WGL_STEREO_ARB))
u->stereo = true;
if (getPixelFormatAttrib(window, n, WGL_DOUBLE_BUFFER_ARB))
u->doublebuffer = true;
if (_glfw.wgl.ARB_multisample)
u->samples = getPixelFormatAttrib(window, n, WGL_SAMPLES_ARB);
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (_glfw.wgl.ARB_framebuffer_sRGB ||
_glfw.wgl.EXT_framebuffer_sRGB)
{
if (getPixelFormatAttrib(window, n, WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB))
u->sRGB = true;
}
}
else
{
if (_glfw.wgl.EXT_colorspace)
{
if (getPixelFormatAttrib(window, n, WGL_COLORSPACE_EXT) ==
WGL_COLORSPACE_SRGB_EXT)
{
u->sRGB = true;
}
}
}
}
else
{
// Get pixel format attributes through legacy PFDs
PIXELFORMATDESCRIPTOR pfd;
if (!DescribePixelFormat(window->context.wgl.dc,
n,
sizeof(PIXELFORMATDESCRIPTOR),
&pfd))
{
continue;
}
if (!(pfd.dwFlags & PFD_DRAW_TO_WINDOW) ||
!(pfd.dwFlags & PFD_SUPPORT_OPENGL))
{
continue;
}
if (!(pfd.dwFlags & PFD_GENERIC_ACCELERATED) &&
(pfd.dwFlags & PFD_GENERIC_FORMAT))
{
continue;
}
if (pfd.iPixelType != PFD_TYPE_RGBA)
continue;
u->redBits = pfd.cRedBits;
u->greenBits = pfd.cGreenBits;
u->blueBits = pfd.cBlueBits;
u->alphaBits = pfd.cAlphaBits;
u->depthBits = pfd.cDepthBits;
u->stencilBits = pfd.cStencilBits;
u->accumRedBits = pfd.cAccumRedBits;
u->accumGreenBits = pfd.cAccumGreenBits;
u->accumBlueBits = pfd.cAccumBlueBits;
u->accumAlphaBits = pfd.cAccumAlphaBits;
u->auxBuffers = pfd.cAuxBuffers;
if (pfd.dwFlags & PFD_STEREO)
u->stereo = true;
if (pfd.dwFlags & PFD_DOUBLEBUFFER)
u->doublebuffer = true;
}
u->handle = n;
usableCount++;
}
if (!usableCount)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"WGL: The driver does not appear to support OpenGL");
free(usableConfigs);
return 0;
}
closest = _glfwChooseFBConfig(fbconfig, usableConfigs, usableCount);
if (!closest)
{
_glfwInputError(GLFW_FORMAT_UNAVAILABLE,
"WGL: Failed to find a suitable pixel format");
free(usableConfigs);
return 0;
}
pixelFormat = (int) closest->handle;
free(usableConfigs);
return pixelFormat;
}
static void makeContextCurrentWGL(_GLFWwindow* window)
{
if (window)
{
if (wglMakeCurrent(window->context.wgl.dc, window->context.wgl.handle))
_glfwPlatformSetTls(&_glfw.contextSlot, window);
else
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make context current");
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
}
}
else
{
if (!wglMakeCurrent(NULL, NULL))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to clear current context");
}
_glfwPlatformSetTls(&_glfw.contextSlot, NULL);
}
}
static void swapBuffersWGL(_GLFWwindow* window)
{
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Use DwmFlush when desktop composition is enabled
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
{
int count = abs(window->context.wgl.interval);
while (count--)
DwmFlush();
}
}
}
SwapBuffers(window->context.wgl.dc);
}
static void swapIntervalWGL(int interval)
{
_GLFWwindow* window = _glfwPlatformGetTls(&_glfw.contextSlot);
window->context.wgl.interval = interval;
if (!window->monitor)
{
if (IsWindowsVistaOrGreater())
{
BOOL enabled;
// HACK: Disable WGL swap interval when desktop composition is enabled to
// avoid interfering with DWM vsync
if (SUCCEEDED(DwmIsCompositionEnabled(&enabled)) && enabled)
interval = 0;
}
}
if (_glfw.wgl.EXT_swap_control)
_glfw.wgl.SwapIntervalEXT(interval);
}
static int extensionSupportedWGL(const char* extension)
{
const char* extensions;
if (_glfw.wgl.GetExtensionsStringEXT)
{
extensions = _glfw.wgl.GetExtensionsStringEXT();
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return true;
}
}
if (_glfw.wgl.GetExtensionsStringARB)
{
extensions = _glfw.wgl.GetExtensionsStringARB(wglGetCurrentDC());
if (extensions)
{
if (_glfwStringInExtensionString(extension, extensions))
return true;
}
}
return false;
}
static GLFWglproc getProcAddressWGL(const char* procname)
{
const GLFWglproc proc = (GLFWglproc) wglGetProcAddress(procname);
if (proc)
return proc;
return (GLFWglproc) GetProcAddress(_glfw.wgl.instance, procname);
}
// Destroy the OpenGL context
//
static void destroyContextWGL(_GLFWwindow* window)
{
if (window->context.wgl.handle)
{
wglDeleteContext(window->context.wgl.handle);
window->context.wgl.handle = NULL;
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW internal API //////
//////////////////////////////////////////////////////////////////////////
// Initialize WGL
//
bool _glfwInitWGL(void)
{
PIXELFORMATDESCRIPTOR pfd;
HGLRC prc, rc;
HDC pdc, dc;
if (_glfw.wgl.instance)
return true;
_glfw.wgl.instance = LoadLibraryA("opengl32.dll");
if (!_glfw.wgl.instance)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to load opengl32.dll");
return false;
}
_glfw.wgl.CreateContext = (PFN_wglCreateContext)
GetProcAddress(_glfw.wgl.instance, "wglCreateContext");
_glfw.wgl.DeleteContext = (PFN_wglDeleteContext)
GetProcAddress(_glfw.wgl.instance, "wglDeleteContext");
_glfw.wgl.GetProcAddress = (PFN_wglGetProcAddress)
GetProcAddress(_glfw.wgl.instance, "wglGetProcAddress");
_glfw.wgl.GetCurrentDC = (PFN_wglGetCurrentDC)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentDC");
_glfw.wgl.GetCurrentContext = (PFN_wglGetCurrentContext)
GetProcAddress(_glfw.wgl.instance, "wglGetCurrentContext");
_glfw.wgl.MakeCurrent = (PFN_wglMakeCurrent)
GetProcAddress(_glfw.wgl.instance, "wglMakeCurrent");
_glfw.wgl.ShareLists = (PFN_wglShareLists)
GetProcAddress(_glfw.wgl.instance, "wglShareLists");
// NOTE: A dummy context has to be created for opengl32.dll to load the
// OpenGL ICD, from which we can then query WGL extensions
// NOTE: This code will accept the Microsoft GDI ICD; accelerated context
// creation failure occurs during manual pixel format enumeration
dc = GetDC(_glfw.win32.helperWindowHandle);
ZeroMemory(&pfd, sizeof(pfd));
pfd.nSize = sizeof(pfd);
pfd.nVersion = 1;
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.cColorBits = 24;
if (!SetPixelFormat(dc, ChoosePixelFormat(dc, &pfd), &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set pixel format for dummy context");
return false;
}
rc = wglCreateContext(dc);
if (!rc)
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to create dummy context");
return false;
}
pdc = wglGetCurrentDC();
prc = wglGetCurrentContext();
if (!wglMakeCurrent(dc, rc))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to make dummy context current");
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc);
return false;
}
// NOTE: Functions must be loaded first as they're needed to retrieve the
// extension string that tells us whether the functions are supported
_glfw.wgl.GetExtensionsStringEXT = (PFNWGLGETEXTENSIONSSTRINGEXTPROC)
wglGetProcAddress("wglGetExtensionsStringEXT");
_glfw.wgl.GetExtensionsStringARB = (PFNWGLGETEXTENSIONSSTRINGARBPROC)
wglGetProcAddress("wglGetExtensionsStringARB");
_glfw.wgl.CreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)
wglGetProcAddress("wglCreateContextAttribsARB");
_glfw.wgl.SwapIntervalEXT = (PFNWGLSWAPINTERVALEXTPROC)
wglGetProcAddress("wglSwapIntervalEXT");
_glfw.wgl.GetPixelFormatAttribivARB = (PFNWGLGETPIXELFORMATATTRIBIVARBPROC)
wglGetProcAddress("wglGetPixelFormatAttribivARB");
// NOTE: WGL_ARB_extensions_string and WGL_EXT_extensions_string are not
// checked below as we are already using them
_glfw.wgl.ARB_multisample =
extensionSupportedWGL("WGL_ARB_multisample");
_glfw.wgl.ARB_framebuffer_sRGB =
extensionSupportedWGL("WGL_ARB_framebuffer_sRGB");
_glfw.wgl.EXT_framebuffer_sRGB =
extensionSupportedWGL("WGL_EXT_framebuffer_sRGB");
_glfw.wgl.ARB_create_context =
extensionSupportedWGL("WGL_ARB_create_context");
_glfw.wgl.ARB_create_context_profile =
extensionSupportedWGL("WGL_ARB_create_context_profile");
_glfw.wgl.EXT_create_context_es2_profile =
extensionSupportedWGL("WGL_EXT_create_context_es2_profile");
_glfw.wgl.ARB_create_context_robustness =
extensionSupportedWGL("WGL_ARB_create_context_robustness");
_glfw.wgl.ARB_create_context_no_error =
extensionSupportedWGL("WGL_ARB_create_context_no_error");
_glfw.wgl.EXT_swap_control =
extensionSupportedWGL("WGL_EXT_swap_control");
_glfw.wgl.EXT_colorspace =
extensionSupportedWGL("WGL_EXT_colorspace");
_glfw.wgl.ARB_pixel_format =
extensionSupportedWGL("WGL_ARB_pixel_format");
_glfw.wgl.ARB_context_flush_control =
extensionSupportedWGL("WGL_ARB_context_flush_control");
wglMakeCurrent(pdc, prc);
wglDeleteContext(rc);
return true;
}
// Terminate WGL
//
void _glfwTerminateWGL(void)
{
if (_glfw.wgl.instance)
FreeLibrary(_glfw.wgl.instance);
}
#define setAttrib(a, v) \
{ \
assert((size_t) (index + 1) < sizeof(attribs) / sizeof(attribs[0])); \
attribs[index++] = a; \
attribs[index++] = v; \
}
// Create the OpenGL or OpenGL ES context
//
bool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig)
{
int attribs[40];
int pixelFormat;
PIXELFORMATDESCRIPTOR pfd;
HGLRC share = NULL;
if (ctxconfig->share)
share = ctxconfig->share->context.wgl.handle;
window->context.wgl.dc = GetDC(window->win32.handle);
if (!window->context.wgl.dc)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve DC for window");
return false;
}
pixelFormat = choosePixelFormat(window, ctxconfig, fbconfig);
if (!pixelFormat)
return false;
if (!DescribePixelFormat(window->context.wgl.dc,
pixelFormat, sizeof(pfd), &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to retrieve PFD for selected pixel format");
return false;
}
if (!SetPixelFormat(window->context.wgl.dc, pixelFormat, &pfd))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to set selected pixel format");
return false;
}
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
{
if (!_glfw.wgl.ARB_create_context)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: A forward compatible OpenGL context requested but WGL_ARB_create_context is unavailable");
return false;
}
}
if (ctxconfig->profile)
{
if (!_glfw.wgl.ARB_create_context_profile)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: OpenGL profile requested but WGL_ARB_create_context_profile is unavailable");
return false;
}
}
}
else
{
if (!_glfw.wgl.ARB_create_context ||
!_glfw.wgl.ARB_create_context_profile ||
!_glfw.wgl.EXT_create_context_es2_profile)
{
_glfwInputError(GLFW_API_UNAVAILABLE,
"WGL: OpenGL ES requested but WGL_ARB_create_context_es2_profile is unavailable");
return false;
}
}
if (_glfw.wgl.ARB_create_context)
{
int index = 0, mask = 0, flags = 0;
if (ctxconfig->client == GLFW_OPENGL_API)
{
if (ctxconfig->forward)
flags |= WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB;
if (ctxconfig->profile == GLFW_OPENGL_CORE_PROFILE)
mask |= WGL_CONTEXT_CORE_PROFILE_BIT_ARB;
else if (ctxconfig->profile == GLFW_OPENGL_COMPAT_PROFILE)
mask |= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB;
}
else
mask |= WGL_CONTEXT_ES2_PROFILE_BIT_EXT;
if (ctxconfig->debug)
flags |= WGL_CONTEXT_DEBUG_BIT_ARB;
if (ctxconfig->robustness)
{
if (_glfw.wgl.ARB_create_context_robustness)
{
if (ctxconfig->robustness == GLFW_NO_RESET_NOTIFICATION)
{
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_NO_RESET_NOTIFICATION_ARB);
}
else if (ctxconfig->robustness == GLFW_LOSE_CONTEXT_ON_RESET)
{
setAttrib(WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB,
WGL_LOSE_CONTEXT_ON_RESET_ARB);
}
flags |= WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB;
}
}
if (ctxconfig->release)
{
if (_glfw.wgl.ARB_context_flush_control)
{
if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_NONE)
{
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB);
}
else if (ctxconfig->release == GLFW_RELEASE_BEHAVIOR_FLUSH)
{
setAttrib(WGL_CONTEXT_RELEASE_BEHAVIOR_ARB,
WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB);
}
}
}
if (ctxconfig->noerror)
{
if (_glfw.wgl.ARB_create_context_no_error)
setAttrib(WGL_CONTEXT_OPENGL_NO_ERROR_ARB, true);
}
// NOTE: Only request an explicitly versioned context when necessary, as
// explicitly requesting version 1.0 does not always return the
// highest version supported by the driver
if (ctxconfig->major != 1 || ctxconfig->minor != 0)
{
setAttrib(WGL_CONTEXT_MAJOR_VERSION_ARB, ctxconfig->major);
setAttrib(WGL_CONTEXT_MINOR_VERSION_ARB, ctxconfig->minor);
}
if (flags)
setAttrib(WGL_CONTEXT_FLAGS_ARB, flags);
if (mask)
setAttrib(WGL_CONTEXT_PROFILE_MASK_ARB, mask);
setAttrib(0, 0);
window->context.wgl.handle =
_glfw.wgl.CreateContextAttribsARB(window->context.wgl.dc,
share, attribs);
if (!window->context.wgl.handle)
{
const DWORD error = GetLastError();
if (error == (0xc0070000 | ERROR_INVALID_VERSION_ARB))
{
if (ctxconfig->client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support OpenGL version %i.%i",
ctxconfig->major,
ctxconfig->minor);
}
else
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support OpenGL ES version %i.%i",
ctxconfig->major,
ctxconfig->minor);
}
}
else if (error == (0xc0070000 | ERROR_INVALID_PROFILE_ARB))
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Driver does not support the requested OpenGL profile");
}
else if (error == (0xc0070000 | ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB))
{
_glfwInputError(GLFW_INVALID_VALUE,
"WGL: The share context is not compatible with the requested context");
}
else
{
if (ctxconfig->client == GLFW_OPENGL_API)
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context");
}
else
{
_glfwInputError(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL ES context");
}
}
return false;
}
}
else
{
window->context.wgl.handle = wglCreateContext(window->context.wgl.dc);
if (!window->context.wgl.handle)
{
_glfwInputErrorWin32(GLFW_VERSION_UNAVAILABLE,
"WGL: Failed to create OpenGL context");
return false;
}
if (share)
{
if (!wglShareLists(share, window->context.wgl.handle))
{
_glfwInputErrorWin32(GLFW_PLATFORM_ERROR,
"WGL: Failed to enable sharing with specified OpenGL context");
return false;
}
}
}
window->context.makeCurrent = makeContextCurrentWGL;
window->context.swapBuffers = swapBuffersWGL;
window->context.swapInterval = swapIntervalWGL;
window->context.extensionSupported = extensionSupportedWGL;
window->context.getProcAddress = getProcAddressWGL;
window->context.destroy = destroyContextWGL;
return true;
}
#undef setAttrib
//////////////////////////////////////////////////////////////////////////
////// GLFW native API //////
//////////////////////////////////////////////////////////////////////////
GLFWAPI HGLRC glfwGetWGLContext(GLFWwindow* handle)
{
_GLFWwindow* window = (_GLFWwindow*) handle;
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
if (window->context.client == GLFW_NO_API)
{
_glfwInputError(GLFW_NO_WINDOW_CONTEXT, NULL);
return NULL;
}
return window->context.wgl.handle;
}

159
glfw/wgl_context.h vendored
View File

@@ -1,159 +0,0 @@
//========================================================================
// GLFW 3.3 WGL - www.glfw.org
//------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-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.
//
//========================================================================
#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000
#define WGL_SUPPORT_OPENGL_ARB 0x2010
#define WGL_DRAW_TO_WINDOW_ARB 0x2001
#define WGL_PIXEL_TYPE_ARB 0x2013
#define WGL_TYPE_RGBA_ARB 0x202b
#define WGL_ACCELERATION_ARB 0x2003
#define WGL_NO_ACCELERATION_ARB 0x2025
#define WGL_RED_BITS_ARB 0x2015
#define WGL_RED_SHIFT_ARB 0x2016
#define WGL_GREEN_BITS_ARB 0x2017
#define WGL_GREEN_SHIFT_ARB 0x2018
#define WGL_BLUE_BITS_ARB 0x2019
#define WGL_BLUE_SHIFT_ARB 0x201a
#define WGL_ALPHA_BITS_ARB 0x201b
#define WGL_ALPHA_SHIFT_ARB 0x201c
#define WGL_ACCUM_BITS_ARB 0x201d
#define WGL_ACCUM_RED_BITS_ARB 0x201e
#define WGL_ACCUM_GREEN_BITS_ARB 0x201f
#define WGL_ACCUM_BLUE_BITS_ARB 0x2020
#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021
#define WGL_DEPTH_BITS_ARB 0x2022
#define WGL_STENCIL_BITS_ARB 0x2023
#define WGL_AUX_BUFFERS_ARB 0x2024
#define WGL_STEREO_ARB 0x2012
#define WGL_DOUBLE_BUFFER_ARB 0x2011
#define WGL_SAMPLES_ARB 0x2042
#define WGL_FRAMEBUFFER_SRGB_CAPABLE_ARB 0x20a9
#define WGL_CONTEXT_DEBUG_BIT_ARB 0x00000001
#define WGL_CONTEXT_FORWARD_COMPATIBLE_BIT_ARB 0x00000002
#define WGL_CONTEXT_PROFILE_MASK_ARB 0x9126
#define WGL_CONTEXT_CORE_PROFILE_BIT_ARB 0x00000001
#define WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB 0x00000002
#define WGL_CONTEXT_MAJOR_VERSION_ARB 0x2091
#define WGL_CONTEXT_MINOR_VERSION_ARB 0x2092
#define WGL_CONTEXT_FLAGS_ARB 0x2094
#define WGL_CONTEXT_ES2_PROFILE_BIT_EXT 0x00000004
#define WGL_CONTEXT_ROBUST_ACCESS_BIT_ARB 0x00000004
#define WGL_LOSE_CONTEXT_ON_RESET_ARB 0x8252
#define WGL_CONTEXT_RESET_NOTIFICATION_STRATEGY_ARB 0x8256
#define WGL_NO_RESET_NOTIFICATION_ARB 0x8261
#define WGL_CONTEXT_RELEASE_BEHAVIOR_ARB 0x2097
#define WGL_CONTEXT_RELEASE_BEHAVIOR_NONE_ARB 0
#define WGL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_ARB 0x2098
#define WGL_CONTEXT_OPENGL_NO_ERROR_ARB 0x31b3
#define WGL_COLORSPACE_EXT 0x309d
#define WGL_COLORSPACE_SRGB_EXT 0x3089
#define ERROR_INVALID_VERSION_ARB 0x2095
#define ERROR_INVALID_PROFILE_ARB 0x2096
#define ERROR_INCOMPATIBLE_DEVICE_CONTEXTS_ARB 0x2054
typedef BOOL (WINAPI * PFNWGLSWAPINTERVALEXTPROC)(int);
typedef BOOL (WINAPI * PFNWGLGETPIXELFORMATATTRIBIVARBPROC)(HDC,int,int,UINT,const int*,int*);
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGEXTPROC)(void);
typedef const char* (WINAPI * PFNWGLGETEXTENSIONSSTRINGARBPROC)(HDC);
typedef HGLRC (WINAPI * PFNWGLCREATECONTEXTATTRIBSARBPROC)(HDC,HGLRC,const int*);
typedef HGLRC (WINAPI * PFN_wglCreateContext)(HDC);
typedef BOOL (WINAPI * PFN_wglDeleteContext)(HGLRC);
typedef PROC (WINAPI * PFN_wglGetProcAddress)(LPCSTR);
typedef HDC (WINAPI * PFN_wglGetCurrentDC)(void);
typedef HGLRC (WINAPI * PFN_wglGetCurrentContext)(void);
typedef BOOL (WINAPI * PFN_wglMakeCurrent)(HDC,HGLRC);
typedef BOOL (WINAPI * PFN_wglShareLists)(HGLRC,HGLRC);
// opengl32.dll function pointer typedefs
#define wglCreateContext _glfw.wgl.CreateContext
#define wglDeleteContext _glfw.wgl.DeleteContext
#define wglGetProcAddress _glfw.wgl.GetProcAddress
#define wglGetCurrentDC _glfw.wgl.GetCurrentDC
#define wglGetCurrentContext _glfw.wgl.GetCurrentContext
#define wglMakeCurrent _glfw.wgl.MakeCurrent
#define wglShareLists _glfw.wgl.ShareLists
#define _GLFW_RECREATION_NOT_NEEDED 0
#define _GLFW_RECREATION_REQUIRED 1
#define _GLFW_RECREATION_IMPOSSIBLE 2
#define _GLFW_PLATFORM_CONTEXT_STATE _GLFWcontextWGL wgl
#define _GLFW_PLATFORM_LIBRARY_CONTEXT_STATE _GLFWlibraryWGL wgl
// WGL-specific per-context data
//
typedef struct _GLFWcontextWGL
{
HDC dc;
HGLRC handle;
int interval;
} _GLFWcontextWGL;
// WGL-specific global data
//
typedef struct _GLFWlibraryWGL
{
HINSTANCE instance;
PFN_wglCreateContext CreateContext;
PFN_wglDeleteContext DeleteContext;
PFN_wglGetProcAddress GetProcAddress;
PFN_wglGetCurrentDC GetCurrentDC;
PFN_wglGetCurrentContext GetCurrentContext;
PFN_wglMakeCurrent MakeCurrent;
PFN_wglShareLists ShareLists;
PFNWGLSWAPINTERVALEXTPROC SwapIntervalEXT;
PFNWGLGETPIXELFORMATATTRIBIVARBPROC GetPixelFormatAttribivARB;
PFNWGLGETEXTENSIONSSTRINGEXTPROC GetExtensionsStringEXT;
PFNWGLGETEXTENSIONSSTRINGARBPROC GetExtensionsStringARB;
PFNWGLCREATECONTEXTATTRIBSARBPROC CreateContextAttribsARB;
bool EXT_swap_control;
bool EXT_colorspace;
bool ARB_multisample;
bool ARB_framebuffer_sRGB;
bool EXT_framebuffer_sRGB;
bool ARB_pixel_format;
bool ARB_create_context;
bool ARB_create_context_profile;
bool EXT_create_context_es2_profile;
bool ARB_create_context_robustness;
bool ARB_create_context_no_error;
bool ARB_context_flush_control;
} _GLFWlibraryWGL;
bool _glfwInitWGL(void);
void _glfwTerminateWGL(void);
bool _glfwCreateContextWGL(_GLFWwindow* window,
const _GLFWctxconfig* ctxconfig,
const _GLFWfbconfig* fbconfig);

10
glfw/window.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 - www.glfw.org // GLFW 3.4 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net> // Copyright (c) 2012 Torsten Walluhn <tw@mad-cad.net>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
@@ -25,6 +25,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// Please use C89 style variable declarations in this file because VS 2010
//========================================================================
#include "internal.h" #include "internal.h"
@@ -82,7 +84,7 @@ _GLFWwindow* _glfwFocusedWindow() {
_GLFWwindow* _glfwWindowForId(GLFWid id) { _GLFWwindow* _glfwWindowForId(GLFWid id) {
_GLFWwindow *w = _glfw.windowListHead; _GLFWwindow *w = _glfw.windowListHead;
while (w) { while (w) {
if (w->id == _glfw.focusedWindowId) return w; if (w->id == id) return w;
w = w->next; w = w->next;
} }
return NULL; return NULL;
@@ -181,7 +183,6 @@ void _glfwInputWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor)
window->monitor = monitor; window->monitor = monitor;
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW public API ////// ////// GLFW public API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -1165,6 +1166,5 @@ GLFWAPI GLFWwindowcontentscalefun glfwSetWindowContentScaleCallback(GLFWwindow*
GLFWAPI void glfwPostEmptyEvent(void) GLFWAPI void glfwPostEmptyEvent(void)
{ {
_GLFW_REQUIRE_INIT(); _GLFW_REQUIRE_INIT();
_glfwPlatformPostEmptyEvent(); _glfwPlatformPostEmptyEvent();
} }

155
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> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@@ -23,6 +23,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#define _GNU_SOURCE #define _GNU_SOURCE
#include "internal.h" #include "internal.h"
@@ -31,7 +33,6 @@
#include <assert.h> #include <assert.h>
#include <errno.h> #include <errno.h>
#include <limits.h> #include <limits.h>
#include <linux/input.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@@ -39,6 +40,16 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
#include <wayland-client.h> #include <wayland-client.h>
// Needed for the BTN_* defines
#ifdef __has_include
#if __has_include(<linux/input.h>)
#include <linux/input.h>
#elif __has_include(<dev/evdev/input.h>)
#include <dev/evdev/input.h>
#endif
#else
#include <linux/input.h>
#endif
static inline int min(int n1, int n2) static inline int min(int n1, int n2)
@@ -46,7 +57,8 @@ static inline int min(int n1, int n2)
return n1 < n2 ? n1 : n2; return n1 < n2 ? n1 : n2;
} }
static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface, int* which) static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
int* which)
{ {
int focus; int focus;
_GLFWwindow* window = _glfw.windowListHead; _GLFWwindow* window = _glfw.windowListHead;
@@ -79,12 +91,12 @@ static _GLFWwindow* findWindowFromDecorationSurface(struct wl_surface* surface,
return window; return window;
} }
static void pointerHandleEnter(void* data, static void pointerHandleEnter(void* data UNUSED,
struct wl_pointer* pointer, struct wl_pointer* pointer UNUSED,
uint32_t serial, uint32_t serial,
struct wl_surface* surface, struct wl_surface* surface,
wl_fixed_t sx, wl_fixed_t sx UNUSED,
wl_fixed_t sy) wl_fixed_t sy UNUSED)
{ {
// Happens in the case we just destroyed the surface. // Happens in the case we just destroyed the surface.
if (!surface) if (!surface)
@@ -109,10 +121,10 @@ static void pointerHandleEnter(void* data,
_glfwInputCursorEnter(window, true); _glfwInputCursorEnter(window, true);
} }
static void pointerHandleLeave(void* data, static void pointerHandleLeave(void* data UNUSED,
struct wl_pointer* pointer, struct wl_pointer* pointer UNUSED,
uint32_t serial, uint32_t serial,
struct wl_surface* surface) struct wl_surface* surface UNUSED)
{ {
_GLFWwindow* window = _glfw.wl.pointerFocus; _GLFWwindow* window = _glfw.wl.pointerFocus;
@@ -154,9 +166,9 @@ static void setCursor(GLFWCursorShape shape)
wl_surface_commit(surface); wl_surface_commit(surface);
} }
static void pointerHandleMotion(void* data, static void pointerHandleMotion(void* data UNUSED,
struct wl_pointer* pointer, struct wl_pointer* pointer UNUSED,
uint32_t time, uint32_t time UNUSED,
wl_fixed_t sx, wl_fixed_t sx,
wl_fixed_t sy) wl_fixed_t sy)
{ {
@@ -174,7 +186,8 @@ static void pointerHandleMotion(void* data,
switch (window->wl.decorations.focus) switch (window->wl.decorations.focus)
{ {
case mainWindow: case mainWindow:
_glfwInputCursorPos(window, window->wl.cursorPosX, window->wl.cursorPosY); _glfwInputCursorPos(window,
window->wl.cursorPosX, window->wl.cursorPosY);
return; return;
case topDecoration: case topDecoration:
if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH) if (window->wl.cursorPosY < _GLFW_DECORATION_WIDTH)
@@ -208,16 +221,15 @@ static void pointerHandleMotion(void* data,
setCursor(cursorShape); setCursor(cursorShape);
} }
static void pointerHandleButton(void* data, static void pointerHandleButton(void* data UNUSED,
struct wl_pointer* pointer, struct wl_pointer* pointer UNUSED,
uint32_t serial, uint32_t serial,
uint32_t time, uint32_t time UNUSED,
uint32_t button, uint32_t button,
uint32_t state) uint32_t state)
{ {
_GLFWwindow* window = _glfw.wl.pointerFocus; _GLFWwindow* window = _glfw.wl.pointerFocus;
int glfwButton; int glfwButton;
uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE; uint32_t edges = XDG_TOPLEVEL_RESIZE_EDGE_NONE;
if (!window) if (!window)
@@ -296,9 +308,9 @@ static void pointerHandleButton(void* data,
_glfw.wl.xkb.states.modifiers); _glfw.wl.xkb.states.modifiers);
} }
static void pointerHandleAxis(void* data, static void pointerHandleAxis(void* data UNUSED,
struct wl_pointer* pointer, struct wl_pointer* pointer UNUSED,
uint32_t time, uint32_t time UNUSED,
uint32_t axis, uint32_t axis,
wl_fixed_t value) wl_fixed_t value)
{ {
@@ -326,8 +338,8 @@ static const struct wl_pointer_listener pointerListener = {
pointerHandleAxis, pointerHandleAxis,
}; };
static void keyboardHandleKeymap(void* data, static void keyboardHandleKeymap(void* data UNUSED,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard UNUSED,
uint32_t format, uint32_t format,
int fd, int fd,
uint32_t size) uint32_t size)
@@ -351,11 +363,11 @@ static void keyboardHandleKeymap(void* data,
} }
static void keyboardHandleEnter(void* data, static void keyboardHandleEnter(void* data UNUSED,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard UNUSED,
uint32_t serial, uint32_t serial UNUSED,
struct wl_surface* surface, struct wl_surface* surface,
struct wl_array* keys) struct wl_array* keys UNUSED)
{ {
// Happens in the case we just destroyed the surface. // Happens in the case we just destroyed the surface.
if (!surface) if (!surface)
@@ -373,10 +385,10 @@ static void keyboardHandleEnter(void* data,
_glfwInputWindowFocus(window, true); _glfwInputWindowFocus(window, true);
} }
static void keyboardHandleLeave(void* data, static void keyboardHandleLeave(void* data UNUSED,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard UNUSED,
uint32_t serial, uint32_t serial UNUSED,
struct wl_surface* surface) struct wl_surface* surface UNUSED)
{ {
_GLFWwindow* window = _glfw.wl.keyboardFocus; _GLFWwindow* window = _glfw.wl.keyboardFocus;
@@ -388,7 +400,7 @@ static void keyboardHandleLeave(void* data,
} }
static void static void
dispatchPendingKeyRepeats(id_type timer_id, void *data) { dispatchPendingKeyRepeats(id_type timer_id UNUSED, void *data UNUSED) {
if (_glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return; 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); 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, (1.0 / (double)_glfw.wl.keyboardRepeatRate));
@@ -396,10 +408,10 @@ dispatchPendingKeyRepeats(id_type timer_id, void *data) {
} }
static void keyboardHandleKey(void* data, static void keyboardHandleKey(void* data UNUSED,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard UNUSED,
uint32_t serial, uint32_t serial UNUSED,
uint32_t time, uint32_t time UNUSED,
uint32_t key, uint32_t key,
uint32_t state) uint32_t state)
{ {
@@ -422,9 +434,9 @@ static void keyboardHandleKey(void* data,
toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, repeatable ? 1 : 0); toggleTimer(&_glfw.wl.eventLoopData, _glfw.wl.keyRepeatInfo.keyRepeatTimer, repeatable ? 1 : 0);
} }
static void keyboardHandleModifiers(void* data, static void keyboardHandleModifiers(void* data UNUSED,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard UNUSED,
uint32_t serial, uint32_t serial UNUSED,
uint32_t modsDepressed, uint32_t modsDepressed,
uint32_t modsLatched, uint32_t modsLatched,
uint32_t modsLocked, uint32_t modsLocked,
@@ -433,7 +445,7 @@ static void keyboardHandleModifiers(void* data,
glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group); glfw_xkb_update_modifiers(&_glfw.wl.xkb, modsDepressed, modsLatched, modsLocked, 0, 0, group);
} }
static void keyboardHandleRepeatInfo(void* data, static void keyboardHandleRepeatInfo(void* data UNUSED,
struct wl_keyboard* keyboard, struct wl_keyboard* keyboard,
int32_t rate, int32_t rate,
int32_t delay) int32_t delay)
@@ -454,7 +466,7 @@ static const struct wl_keyboard_listener keyboardListener = {
keyboardHandleRepeatInfo, keyboardHandleRepeatInfo,
}; };
static void seatHandleCapabilities(void* data, static void seatHandleCapabilities(void* data UNUSED,
struct wl_seat* seat, struct wl_seat* seat,
enum wl_seat_capability caps) enum wl_seat_capability caps)
{ {
@@ -481,9 +493,9 @@ static void seatHandleCapabilities(void* data,
} }
} }
static void seatHandleName(void* data, static void seatHandleName(void* data UNUSED,
struct wl_seat* seat, struct wl_seat* seat UNUSED,
const char* name) const char* name UNUSED)
{ {
} }
@@ -492,7 +504,7 @@ static const struct wl_seat_listener seatListener = {
seatHandleName, seatHandleName,
}; };
static void wmBaseHandlePing(void* data, static void wmBaseHandlePing(void* data UNUSED,
struct xdg_wm_base* wmBase, struct xdg_wm_base* wmBase,
uint32_t serial) uint32_t serial)
{ {
@@ -503,7 +515,7 @@ static const struct xdg_wm_base_listener wmBaseListener = {
wmBaseHandlePing wmBaseHandlePing
}; };
static void registryHandleGlobal(void* data, static void registryHandleGlobal(void* data UNUSED,
struct wl_registry* registry, struct wl_registry* registry,
uint32_t name, uint32_t name,
const char* interface, const char* interface,
@@ -609,8 +621,8 @@ static void registryHandleGlobal(void* data,
} }
static void registryHandleGlobalRemove(void *data, static void registryHandleGlobalRemove(void *data UNUSED,
struct wl_registry *registry, struct wl_registry *registry UNUSED,
uint32_t name) uint32_t name)
{ {
_GLFWmonitor* monitor; _GLFWmonitor* monitor;
@@ -642,19 +654,19 @@ static const struct wl_registry_listener registryListener = {
static void registry_handle_global(void* data, static void registry_handle_global(void* data,
struct wl_registry* registry, struct wl_registry* registry UNUSED,
uint32_t name, uint32_t name UNUSED,
const char* interface, const char* interface,
uint32_t version) { uint32_t version UNUSED) {
if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) { if (strcmp(interface, "zxdg_decoration_manager_v1") == 0) {
bool *has_ssd = (bool*)data; bool *has_ssd = (bool*)data;
if (has_ssd) *has_ssd = true; if (has_ssd) *has_ssd = true;
} }
} }
static void registry_handle_global_remove(void *data, static void registry_handle_global_remove(void *data UNUSED,
struct wl_registry *registry, struct wl_registry *registry UNUSED,
uint32_t name) {} uint32_t name UNUSED) {}
GLFWAPI const char* GLFWAPI const char*
glfwWaylandCheckForServerSideDecorations(void) { glfwWaylandCheckForServerSideDecorations(void) {
struct wl_display *display = wl_display_connect(NULL); struct wl_display *display = wl_display_connect(NULL);
@@ -679,13 +691,6 @@ glfwWaylandCheckForServerSideDecorations(void) {
int _glfwPlatformInit(void) int _glfwPlatformInit(void)
{ {
if (pipe2(_glfw.wl.eventLoopData.wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: failed to create self pipe");
return false;
}
_glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0"); _glfw.wl.cursor.handle = _glfw_dlopen("libwayland-cursor.so.0");
if (!_glfw.wl.cursor.handle) if (!_glfw.wl.cursor.handle)
{ {
@@ -694,14 +699,10 @@ int _glfwPlatformInit(void)
return false; return false;
} }
_glfw.wl.cursor.theme_load = (PFN_wl_cursor_theme_load) glfw_dlsym(_glfw.wl.cursor.theme_load, _glfw.wl.cursor.handle, "wl_cursor_theme_load");
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_load"); glfw_dlsym(_glfw.wl.cursor.theme_destroy, _glfw.wl.cursor.handle, "wl_cursor_theme_destroy");
_glfw.wl.cursor.theme_destroy = (PFN_wl_cursor_theme_destroy) glfw_dlsym(_glfw.wl.cursor.theme_get_cursor, _glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_destroy"); glfw_dlsym(_glfw.wl.cursor.image_get_buffer, _glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
_glfw.wl.cursor.theme_get_cursor = (PFN_wl_cursor_theme_get_cursor)
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_theme_get_cursor");
_glfw.wl.cursor.image_get_buffer = (PFN_wl_cursor_image_get_buffer)
_glfw_dlsym(_glfw.wl.cursor.handle, "wl_cursor_image_get_buffer");
_glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1"); _glfw.wl.egl.handle = _glfw_dlopen("libwayland-egl.so.1");
if (!_glfw.wl.egl.handle) if (!_glfw.wl.egl.handle)
@@ -711,12 +712,9 @@ int _glfwPlatformInit(void)
return false; return false;
} }
_glfw.wl.egl.window_create = (PFN_wl_egl_window_create) glfw_dlsym(_glfw.wl.egl.window_create, _glfw.wl.egl.handle, "wl_egl_window_create");
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_create"); glfw_dlsym(_glfw.wl.egl.window_destroy, _glfw.wl.egl.handle, "wl_egl_window_destroy");
_glfw.wl.egl.window_destroy = (PFN_wl_egl_window_destroy) glfw_dlsym(_glfw.wl.egl.window_resize, _glfw.wl.egl.handle, "wl_egl_window_resize");
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_destroy");
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
_glfw.wl.display = wl_display_connect(NULL); _glfw.wl.display = wl_display_connect(NULL);
if (!_glfw.wl.display) if (!_glfw.wl.display)
@@ -725,7 +723,10 @@ int _glfwPlatformInit(void)
"Wayland: Failed to connect to display"); "Wayland: Failed to connect to display");
return false; return false;
} }
initPollData(&_glfw.wl.eventLoopData, _glfw.wl.eventLoopData.wakeupFds[0], wl_display_get_fd(_glfw.wl.display)); if (!initPollData(&_glfw.wl.eventLoopData, wl_display_get_fd(_glfw.wl.display))) {
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to initialize event loop data");
}
glfw_dbus_init(&_glfw.wl.dbus, &_glfw.wl.eventLoopData); 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.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.cursorAnimationTimer = addTimer(&_glfw.wl.eventLoopData, "wayland-cursor-animation", 0.5, 0, true, animateCursorImage, NULL, NULL);
@@ -853,7 +854,7 @@ void _glfwPlatformTerminate(void)
wl_display_flush(_glfw.wl.display); wl_display_flush(_glfw.wl.display);
wl_display_disconnect(_glfw.wl.display); wl_display_disconnect(_glfw.wl.display);
} }
closeFds(_glfw.wl.eventLoopData.wakeupFds, sizeof(_glfw.wl.eventLoopData.wakeupFds)/sizeof(_glfw.wl.eventLoopData.wakeupFds[0])); finalizePollData(&_glfw.wl.eventLoopData);
free(_glfw.wl.clipboardString); _glfw.wl.clipboardString = NULL; free(_glfw.wl.clipboardString); _glfw.wl.clipboardString = NULL;
free(_glfw.wl.primarySelectionString); _glfw.wl.primarySelectionString = NULL; free(_glfw.wl.primarySelectionString); _glfw.wl.primarySelectionString = NULL;
free(_glfw.wl.pasteString); _glfw.wl.pasteString = NULL; free(_glfw.wl.pasteString); _glfw.wl.pasteString = NULL;

49
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> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@@ -23,6 +23,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -34,15 +36,15 @@
static void outputHandleGeometry(void* data, static void outputHandleGeometry(void* data,
struct wl_output* output, struct wl_output* output UNUSED,
int32_t x, int32_t x,
int32_t y, int32_t y,
int32_t physicalWidth, int32_t physicalWidth,
int32_t physicalHeight, int32_t physicalHeight,
int32_t subpixel, int32_t subpixel UNUSED,
const char* make, const char* make,
const char* model, const char* model,
int32_t transform) int32_t transform UNUSED)
{ {
struct _GLFWmonitor *monitor = data; struct _GLFWmonitor *monitor = data;
char name[1024]; char name[1024];
@@ -57,11 +59,11 @@ static void outputHandleGeometry(void* data,
} }
static void outputHandleMode(void* data, static void outputHandleMode(void* data,
struct wl_output* output, struct wl_output* output UNUSED,
uint32_t flags, uint32_t flags,
int32_t width, int32_t width,
int32_t height, int32_t height,
int32_t refresh) int32_t refresh)
{ {
struct _GLFWmonitor *monitor = data; struct _GLFWmonitor *monitor = data;
GLFWvidmode mode; GLFWvidmode mode;
@@ -71,7 +73,7 @@ static void outputHandleMode(void* data,
mode.redBits = 8; mode.redBits = 8;
mode.greenBits = 8; mode.greenBits = 8;
mode.blueBits = 8; mode.blueBits = 8;
mode.refreshRate = (int)round(refresh / 1000.0); mode.refreshRate = (int) round(refresh / 1000.0);
monitor->modeCount++; monitor->modeCount++;
monitor->modes = monitor->modes =
@@ -82,7 +84,7 @@ static void outputHandleMode(void* data,
monitor->wl.currentMode = monitor->modeCount - 1; monitor->wl.currentMode = monitor->modeCount - 1;
} }
static void outputHandleDone(void* data, struct wl_output* output) static void outputHandleDone(void* data, struct wl_output* output UNUSED)
{ {
struct _GLFWmonitor *monitor = data; struct _GLFWmonitor *monitor = data;
for (int i = 0; i < _glfw.monitorCount; i++) { for (int i = 0; i < _glfw.monitorCount; i++) {
@@ -93,8 +95,8 @@ static void outputHandleDone(void* data, struct wl_output* output)
} }
static void outputHandleScale(void* data, static void outputHandleScale(void* data,
struct wl_output* output, struct wl_output* output UNUSED,
int32_t factor) int32_t factor)
{ {
struct _GLFWmonitor *monitor = data; struct _GLFWmonitor *monitor = data;
if (factor > 0 && factor < 24) if (factor > 0 && factor < 24)
@@ -173,7 +175,9 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
*yscale = (float) monitor->wl.scale; *yscale = (float) monitor->wl.scale;
} }
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor,
int* xpos, int* ypos,
int* width, int* height)
{ {
if (xpos) if (xpos)
*xpos = monitor->wl.x; *xpos = monitor->wl.x;
@@ -196,14 +200,15 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
*mode = monitor->modes[monitor->wl.currentMode]; *mode = monitor->modes[monitor->wl.currentMode];
} }
bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor, GLFWgammaramp* ramp) bool _glfwPlatformGetGammaRamp(_GLFWmonitor* monitor UNUSED, GLFWgammaramp* ramp UNUSED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Gamma ramp access is not available"); "Wayland: Gamma ramp access is not available");
return false; return false;
} }
void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp) void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor UNUSED,
const GLFWgammaramp* ramp UNUSED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Gamma ramp access is not available"); "Wayland: Gamma ramp access is not available");

16
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> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@@ -133,10 +133,10 @@ typedef struct _GLFWdecorationWayland
typedef struct _GLFWwindowWayland typedef struct _GLFWwindowWayland
{ {
int width, height; int width, height;
bool visible; bool visible;
bool maximized; bool maximized;
bool hovered; bool hovered;
bool transparent; bool transparent;
struct wl_surface* surface; struct wl_surface* surface;
struct wl_egl_window* native; struct wl_egl_window* native;
struct wl_callback* callback; struct wl_callback* callback;
@@ -167,10 +167,10 @@ typedef struct _GLFWwindowWayland
struct zwp_idle_inhibitor_v1* idleInhibitor; struct zwp_idle_inhibitor_v1* idleInhibitor;
bool fullscreened; bool fullscreened;
struct { struct {
bool serverSide; bool serverSide;
struct wl_buffer* buffer; struct wl_buffer* buffer;
_GLFWdecorationWayland top, left, right, bottom; _GLFWdecorationWayland top, left, right, bottom;
int focus; int focus;
@@ -295,7 +295,7 @@ typedef struct _GLFWlibraryWayland
typedef struct _GLFWmonitorWayland typedef struct _GLFWmonitorWayland
{ {
struct wl_output* output; struct wl_output* output;
int name; uint32_t name;
int currentMode; int currentMode;
int x; int x;

163
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> // Copyright (c) 2014 Jonas Ådahl <jadahl@gmail.com>
// //
@@ -23,6 +23,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#define _GNU_SOURCE #define _GNU_SOURCE
@@ -171,7 +173,7 @@ static void dispatchChangesAfterConfigure(_GLFWwindow *window, int32_t width, in
* SCM_RIGHTS methods. * SCM_RIGHTS methods.
* *
* posix_fallocate() is used to guarantee that disk space is available * 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 * is set to ENOSPC. If posix_fallocate() is not supported, program may
* receive SIGBUS on accessing mmap()'ed file contents instead. * receive SIGBUS on accessing mmap()'ed file contents instead.
*/ */
@@ -239,7 +241,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
if (fd < 0) if (fd < 0)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Creating a buffer file for %d B failed: %m", "Wayland: Creating a buffer file for %d B failed: %%m",
length); length);
return NULL; return NULL;
} }
@@ -248,7 +250,7 @@ static struct wl_buffer* createShmBuffer(const GLFWimage* image)
if (data == MAP_FAILED) if (data == MAP_FAILED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: mmap failed: %m"); "Wayland: mmap failed: %%m");
close(fd); close(fd);
return NULL; return NULL;
} }
@@ -363,12 +365,12 @@ static void destroyDecorations(_GLFWwindow* window)
} }
static void xdgDecorationHandleConfigure(void* data, static void xdgDecorationHandleConfigure(void* data,
struct zxdg_toplevel_decoration_v1* decoration, struct zxdg_toplevel_decoration_v1* decoration UNUSED,
uint32_t mode) uint32_t mode)
{ {
_GLFWwindow* window = data; _GLFWwindow* window = data;
window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE); window->wl.decorations.serverSide = (mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
if (!window->wl.decorations.serverSide) if (!window->wl.decorations.serverSide)
createDecorations(window); createDecorations(window);
} }
@@ -377,7 +379,7 @@ static const struct zxdg_toplevel_decoration_v1_listener xdgDecorationListener =
}; };
static void handleEnter(void *data, static void handleEnter(void *data,
struct wl_surface *surface, struct wl_surface *surface UNUSED,
struct wl_output *output) struct wl_output *output)
{ {
_GLFWwindow* window = data; _GLFWwindow* window = data;
@@ -400,7 +402,7 @@ static void handleEnter(void *data,
} }
static void handleLeave(void *data, static void handleLeave(void *data,
struct wl_surface *surface, struct wl_surface *surface UNUSED,
struct wl_output *output) struct wl_output *output)
{ {
_GLFWwindow* window = data; _GLFWwindow* window = data;
@@ -496,15 +498,14 @@ setFullscreen(_GLFWwindow* window, _GLFWmonitor* monitor, bool on)
} }
bool bool
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags) { _glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
(void) flags;
bool already_fullscreen = window->wl.fullscreened; bool already_fullscreen = window->wl.fullscreened;
setFullscreen(window, NULL, !already_fullscreen); setFullscreen(window, NULL, !already_fullscreen);
return !already_fullscreen; return !already_fullscreen;
} }
static void xdgToplevelHandleConfigure(void* data, static void xdgToplevelHandleConfigure(void* data,
struct xdg_toplevel* toplevel, struct xdg_toplevel* toplevel UNUSED,
int32_t width, int32_t width,
int32_t height, int32_t height,
struct wl_array* states) struct wl_array* states)
@@ -562,7 +563,7 @@ static void xdgToplevelHandleConfigure(void* data,
} }
static void xdgToplevelHandleClose(void* data, static void xdgToplevelHandleClose(void* data,
struct xdg_toplevel* toplevel) struct xdg_toplevel* toplevel UNUSED)
{ {
_GLFWwindow* window = data; _GLFWwindow* window = data;
_glfwInputWindowCloseRequest(window); _glfwInputWindowCloseRequest(window);
@@ -573,7 +574,7 @@ static const struct xdg_toplevel_listener xdgToplevelListener = {
xdgToplevelHandleClose xdgToplevelHandleClose
}; };
static void xdgSurfaceHandleConfigure(void* data, static void xdgSurfaceHandleConfigure(void* data UNUSED,
struct xdg_surface* surface, struct xdg_surface* surface,
uint32_t serial) uint32_t serial)
{ {
@@ -726,7 +727,7 @@ incrementCursorImage(_GLFWwindow* window)
} }
void void
animateCursorImage(id_type timer_id, void *data) { animateCursorImage(id_type timer_id UNUSED, void *data UNUSED) {
incrementCursorImage(_glfw.wl.pointerFocus); incrementCursorImage(_glfw.wl.pointerFocus);
} }
@@ -739,6 +740,8 @@ abortOnFatalError(int last_error) {
_glfwInputWindowCloseRequest(window); _glfwInputWindowCloseRequest(window);
window = window->next; window = window->next;
} }
// ensure the tick callback is called
_glfw.wl.eventLoopData.wakeup_data_read = true;
} }
static void static void
@@ -746,16 +749,17 @@ handleEvents(double timeout)
{ {
struct wl_display* display = _glfw.wl.display; struct wl_display* display = _glfw.wl.display;
errno = 0; errno = 0;
EVDBG("starting handleEvents(%.2f)", timeout);
while (wl_display_prepare_read(display) != 0) { while (wl_display_prepare_read(display) != 0) {
while(1) { while(1) {
errno = 0; errno = 0;
int num_dispatched = wl_display_dispatch_pending(display); int num_dispatched = wl_display_dispatch_pending(display);
if (num_dispatched == 0) return;
if (num_dispatched < 0) { if (num_dispatched < 0) {
if (errno == EAGAIN) continue; if (errno == EAGAIN) continue;
int last_error = wl_display_get_error(display); int last_error = wl_display_get_error(display);
if (last_error) abortOnFatalError(last_error); if (last_error) abortOnFatalError(last_error);
wl_display_cancel_read(display);
return; return;
} }
break; break;
@@ -774,9 +778,12 @@ handleEvents(double timeout)
} }
bool display_read_ok = pollForEvents(&_glfw.wl.eventLoopData, timeout); bool display_read_ok = pollForEvents(&_glfw.wl.eventLoopData, timeout);
EVDBG("display_read_ok: %d", display_read_ok);
if (display_read_ok) { if (display_read_ok) {
wl_display_read_events(display); wl_display_read_events(display);
wl_display_dispatch_pending(display); int num = wl_display_dispatch_pending(display);
(void)num;
EVDBG("dispatched %d Wayland events", num);
} }
else else
{ {
@@ -784,6 +791,8 @@ handleEvents(double timeout)
} }
glfw_ibus_dispatch(&_glfw.wl.xkb.ibus); glfw_ibus_dispatch(&_glfw.wl.xkb.ibus);
glfw_dbus_session_bus_dispatch(); glfw_dbus_session_bus_dispatch();
EVDBG("other dispatch done");
if (_glfw.wl.eventLoopData.wakeup_fd_ready) check_for_wakeup_events(&_glfw.wl.eventLoopData);
} }
static struct wl_cursor* static struct wl_cursor*
@@ -914,6 +923,7 @@ void _glfwPlatformDestroyWindow(_GLFWwindow* window)
destroyDecorations(window); destroyDecorations(window);
if (window->wl.xdg.decoration) if (window->wl.xdg.decoration)
zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration); zxdg_toplevel_decoration_v1_destroy(window->wl.xdg.decoration);
if (window->wl.decorations.buffer) if (window->wl.decorations.buffer)
wl_buffer_destroy(window->wl.decorations.buffer); wl_buffer_destroy(window->wl.decorations.buffer);
@@ -944,14 +954,14 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title)
xdg_toplevel_set_title(window->wl.xdg.toplevel, title); xdg_toplevel_set_title(window->wl.xdg.toplevel, title);
} }
void _glfwPlatformSetWindowIcon(_GLFWwindow* window, void _glfwPlatformSetWindowIcon(_GLFWwindow* window UNUSED,
int count, const GLFWimage* images) int count UNUSED, const GLFWimage* images UNUSED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Setting window icon not supported"); "Wayland: Setting window icon not supported");
} }
void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos) void _glfwPlatformGetWindowPos(_GLFWwindow* window UNUSED, int* xpos UNUSED, int* ypos UNUSED)
{ {
// A Wayland client is not aware of its position, so just warn and leave it // A Wayland client is not aware of its position, so just warn and leave it
// as (0, 0) // as (0, 0)
@@ -960,7 +970,7 @@ void _glfwPlatformGetWindowPos(_GLFWwindow* window, int* xpos, int* ypos)
"Wayland: Window position retrieval not supported"); "Wayland: Window position retrieval not supported");
} }
void _glfwPlatformSetWindowPos(_GLFWwindow* window, int xpos, int ypos) void _glfwPlatformSetWindowPos(_GLFWwindow* window UNUSED, int xpos UNUSED, int ypos UNUSED)
{ {
// A Wayland client can not set its position, so just warn // A Wayland client can not set its position, so just warn
@@ -1001,13 +1011,15 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
} }
} }
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window UNUSED,
int numer UNUSED, int denom UNUSED)
{ {
// TODO: find out how to trigger a resize. // TODO: find out how to trigger a resize.
// The actual limits are checked in the xdg_toplevel::configure handler. // The actual limits are checked in the xdg_toplevel::configure handler.
} }
void _glfwPlatformGetFramebufferSize(_GLFWwindow* window, int* width, int* height) void _glfwPlatformGetFramebufferSize(_GLFWwindow* window,
int* width, int* height)
{ {
_glfwPlatformGetWindowSize(window, width, height); _glfwPlatformGetWindowSize(window, width, height);
*width *= window->wl.scale; *width *= window->wl.scale;
@@ -1040,7 +1052,7 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
*yscale = (float) window->wl.scale; *yscale = (float) window->wl.scale;
} }
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window) double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
{ {
return 0.5; return 0.5;
} }
@@ -1096,7 +1108,7 @@ void _glfwPlatformHideWindow(_GLFWwindow* window)
window->wl.visible = false; window->wl.visible = false;
} }
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window) void _glfwPlatformRequestWindowAttention(_GLFWwindow* window UNUSED)
{ {
// TODO // TODO
static bool notified = false; static bool notified = false;
@@ -1107,7 +1119,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
} }
} }
int _glfwPlatformWindowBell(_GLFWwindow* window) int _glfwPlatformWindowBell(_GLFWwindow* window UNUSED)
{ {
// TODO: Use an actual Wayland API to implement this when one becomes available // TODO: Use an actual Wayland API to implement this when one becomes available
static char tty[L_ctermid + 1]; static char tty[L_ctermid + 1];
@@ -1120,7 +1132,7 @@ int _glfwPlatformWindowBell(_GLFWwindow* window)
return false; return false;
} }
void _glfwPlatformFocusWindow(_GLFWwindow* window) void _glfwPlatformFocusWindow(_GLFWwindow* window UNUSED)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Focusing a window requires user interaction"); "Wayland: Focusing a window requires user interaction");
@@ -1128,9 +1140,9 @@ void _glfwPlatformFocusWindow(_GLFWwindow* window)
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos UNUSED, int ypos UNUSED,
int width, int height, int width UNUSED, int height UNUSED,
int refreshRate) int refreshRate UNUSED)
{ {
setFullscreen(window, monitor, monitor != NULL); setFullscreen(window, monitor, monitor != NULL);
_glfwInputWindowMonitor(window, monitor); _glfwInputWindowMonitor(window, monitor);
@@ -1141,12 +1153,12 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
return _glfw.wl.keyboardFocus == window; return _glfw.wl.keyboardFocus == window;
} }
int _glfwPlatformWindowOccluded(_GLFWwindow* window) int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
{ {
return false; return false;
} }
int _glfwPlatformWindowIconified(_GLFWwindow* window) int _glfwPlatformWindowIconified(_GLFWwindow* window UNUSED)
{ {
// xdg-shell doesnt give any way to request whether a surface is // xdg-shell doesnt give any way to request whether a surface is
// iconified. // iconified.
@@ -1173,7 +1185,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
return window->wl.transparent; return window->wl.transparent;
} }
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled) void _glfwPlatformSetWindowResizable(_GLFWwindow* window UNUSED, bool enabled UNUSED)
{ {
// TODO // TODO
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
@@ -1191,19 +1203,19 @@ void _glfwPlatformSetWindowDecorated(_GLFWwindow* window, bool enabled)
} }
} }
void _glfwPlatformSetWindowFloating(_GLFWwindow* window, bool enabled) void _glfwPlatformSetWindowFloating(_GLFWwindow* window UNUSED, bool enabled UNUSED)
{ {
// TODO // TODO
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Window attribute setting not implemented yet"); "Wayland: Window attribute setting not implemented yet");
} }
float _glfwPlatformGetWindowOpacity(_GLFWwindow* window) float _glfwPlatformGetWindowOpacity(_GLFWwindow* window UNUSED)
{ {
return 1.f; return 1.f;
} }
void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity) void _glfwPlatformSetWindowOpacity(_GLFWwindow* window UNUSED, float opacity UNUSED)
{ {
} }
@@ -1227,7 +1239,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformPostEmptyEvent(void) void _glfwPlatformPostEmptyEvent(void)
{ {
while (write(_glfw.wl.eventLoopData.wakeupFds[1], "w", 1) < 0 && errno == EINTR); wakeupEventLoop(&_glfw.wl.eventLoopData);
} }
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
@@ -1251,7 +1263,7 @@ void _glfwPlatformSetCursorPos(_GLFWwindow* window, double x, double y)
} }
} }
void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode) void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode UNUSED)
{ {
_glfwPlatformSetCursor(window, window->wl.currentCursor); _glfwPlatformSetCursor(window, window->wl.currentCursor);
} }
@@ -1268,7 +1280,7 @@ int _glfwPlatformGetKeyScancode(int key)
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot, int count) int xhot, int yhot, int count UNUSED)
{ {
cursor->wl.buffer = createShmBuffer(image); cursor->wl.buffer = createShmBuffer(image);
if (!cursor->wl.buffer) if (!cursor->wl.buffer)
@@ -1302,11 +1314,11 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
} }
static void handleRelativeMotion(void* data, static void handleRelativeMotion(void* data,
struct zwp_relative_pointer_v1* pointer, struct zwp_relative_pointer_v1* pointer UNUSED,
uint32_t timeHi, uint32_t timeHi UNUSED,
uint32_t timeLo, uint32_t timeLo UNUSED,
wl_fixed_t dx, wl_fixed_t dx UNUSED,
wl_fixed_t dy, wl_fixed_t dy UNUSED,
wl_fixed_t dxUnaccel, wl_fixed_t dxUnaccel,
wl_fixed_t dyUnaccel) wl_fixed_t dyUnaccel)
{ {
@@ -1324,8 +1336,8 @@ static const struct zwp_relative_pointer_v1_listener relativePointerListener = {
handleRelativeMotion handleRelativeMotion
}; };
static void handleLocked(void* data, static void handleLocked(void* data UNUSED,
struct zwp_locked_pointer_v1* lockedPointer) struct zwp_locked_pointer_v1* lockedPointer UNUSED)
{ {
} }
@@ -1343,10 +1355,10 @@ static void unlockPointer(_GLFWwindow* window)
window->wl.pointerLock.lockedPointer = NULL; window->wl.pointerLock.lockedPointer = NULL;
} }
static void lockPointer(_GLFWwindow* window); static void lockPointer(_GLFWwindow* window UNUSED);
static void handleUnlocked(void* data, static void handleUnlocked(void* data UNUSED,
struct zwp_locked_pointer_v1* lockedPointer) struct zwp_locked_pointer_v1* lockedPointer UNUSED)
{ {
} }
@@ -1468,12 +1480,12 @@ static void send_text(char *text, int fd)
close(fd); close(fd);
} }
static void _glfwSendClipboardText(void *data, struct wl_data_source *data_source, const char *mime_type, int fd) { static void _glfwSendClipboardText(void *data UNUSED, struct wl_data_source *data_source UNUSED, const char *mime_type UNUSED, int fd) {
send_text(_glfw.wl.clipboardString, fd); send_text(_glfw.wl.clipboardString, fd);
} }
static void _glfwSendPrimarySelectionText(void *data, struct zwp_primary_selection_source_v1 *primary_selection_source, static void _glfwSendPrimarySelectionText(void *data UNUSED, struct zwp_primary_selection_source_v1 *primary_selection_source UNUSED,
const char *mime_type, int fd) { const char *mime_type UNUSED, int fd) {
send_text(_glfw.wl.primarySelectionString, fd); send_text(_glfw.wl.primarySelectionString, fd);
} }
@@ -1538,28 +1550,28 @@ static char* read_data_offer(struct wl_data_offer *data_offer, const char *mime)
return read_offer_string(pipefd[0]); return read_offer_string(pipefd[0]);
} }
static void data_source_canceled(void *data, struct wl_data_source *wl_data_source) { static void data_source_canceled(void *data UNUSED, struct wl_data_source *wl_data_source) {
if (_glfw.wl.dataSourceForClipboard == wl_data_source) if (_glfw.wl.dataSourceForClipboard == wl_data_source)
_glfw.wl.dataSourceForClipboard = NULL; _glfw.wl.dataSourceForClipboard = NULL;
wl_data_source_destroy(wl_data_source); wl_data_source_destroy(wl_data_source);
} }
static void primary_selection_source_canceled(void *data, struct zwp_primary_selection_source_v1 *primary_selection_source) { static void primary_selection_source_canceled(void *data UNUSED, struct zwp_primary_selection_source_v1 *primary_selection_source) {
if (_glfw.wl.dataSourceForPrimarySelection == primary_selection_source) if (_glfw.wl.dataSourceForPrimarySelection == primary_selection_source)
_glfw.wl.dataSourceForPrimarySelection = NULL; _glfw.wl.dataSourceForPrimarySelection = NULL;
zwp_primary_selection_source_v1_destroy(primary_selection_source); zwp_primary_selection_source_v1_destroy(primary_selection_source);
} }
static void data_source_target(void *data, struct wl_data_source *wl_data_source, const char* mime) { static void data_source_target(void *data UNUSED, struct wl_data_source *wl_data_source UNUSED, const char* mime UNUSED) {
} }
const static struct wl_data_source_listener data_source_listener = { static const struct wl_data_source_listener data_source_listener = {
.send = _glfwSendClipboardText, .send = _glfwSendClipboardText,
.cancelled = data_source_canceled, .cancelled = data_source_canceled,
.target = data_source_target, .target = data_source_target,
}; };
const static struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = { static const struct zwp_primary_selection_source_v1_listener primary_selection_source_listener = {
.send = _glfwSendPrimarySelectionText, .send = _glfwSendPrimarySelectionText,
.cancelled = primary_selection_source_canceled, .cancelled = primary_selection_source_canceled,
}; };
@@ -1582,7 +1594,7 @@ static void prune_unclaimed_primary_selection_offers(void) {
} }
} }
static void mark_selection_offer(void *data, struct wl_data_device *data_device, struct wl_data_offer *data_offer) static void mark_selection_offer(void *data UNUSED, struct wl_data_device *data_device UNUSED, struct wl_data_offer *data_offer)
{ {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].id == data_offer) { if (_glfw.wl.dataOffers[i].id == data_offer) {
@@ -1594,7 +1606,7 @@ static void mark_selection_offer(void *data, struct wl_data_device *data_device,
prune_unclaimed_data_offers(); prune_unclaimed_data_offers();
} }
static void mark_primary_selection_offer(void *data, struct zwp_primary_selection_device_v1* primary_selection_device, static void mark_primary_selection_offer(void *data UNUSED, struct zwp_primary_selection_device_v1* primary_selection_device UNUSED,
struct zwp_primary_selection_offer_v1 *primary_selection_offer) { struct zwp_primary_selection_offer_v1 *primary_selection_offer) {
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
if (_glfw.wl.primarySelectionOffers[i].id == primary_selection_offer) { if (_glfw.wl.primarySelectionOffers[i].id == primary_selection_offer) {
@@ -1617,7 +1629,7 @@ static void set_offer_mimetype(struct _GLFWWaylandDataOffer* offer, const char*
offer->has_uri_list = 1; offer->has_uri_list = 1;
} }
static void handle_offer_mimetype(void *data, struct wl_data_offer* id, const char *mime) { static void handle_offer_mimetype(void *data UNUSED, struct wl_data_offer* id, const char *mime) {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].id == id) { if (_glfw.wl.dataOffers[i].id == id) {
set_offer_mimetype(&_glfw.wl.dataOffers[i], mime); set_offer_mimetype(&_glfw.wl.dataOffers[i], mime);
@@ -1626,7 +1638,7 @@ static void handle_offer_mimetype(void *data, struct wl_data_offer* id, const ch
} }
} }
static void handle_primary_selection_offer_mimetype(void *data, struct zwp_primary_selection_offer_v1* id, const char *mime) { static void handle_primary_selection_offer_mimetype(void *data UNUSED, struct zwp_primary_selection_offer_v1* id, const char *mime) {
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
if (_glfw.wl.primarySelectionOffers[i].id == id) { if (_glfw.wl.primarySelectionOffers[i].id == id) {
set_offer_mimetype((struct _GLFWWaylandDataOffer*)&_glfw.wl.primarySelectionOffers[i], mime); set_offer_mimetype((struct _GLFWWaylandDataOffer*)&_glfw.wl.primarySelectionOffers[i], mime);
@@ -1635,7 +1647,7 @@ static void handle_primary_selection_offer_mimetype(void *data, struct zwp_prima
} }
} }
static void data_offer_source_actions(void *data, struct wl_data_offer* id, uint32_t actions) { static void data_offer_source_actions(void *data UNUSED, struct wl_data_offer* id, uint32_t actions) {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].id == id) { if (_glfw.wl.dataOffers[i].id == id) {
_glfw.wl.dataOffers[i].source_actions = actions; _glfw.wl.dataOffers[i].source_actions = actions;
@@ -1644,7 +1656,7 @@ static void data_offer_source_actions(void *data, struct wl_data_offer* id, uint
} }
} }
static void data_offer_action(void *data, struct wl_data_offer* id, uint32_t action) { static void data_offer_action(void *data UNUSED, struct wl_data_offer* id, uint32_t action) {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].id == id) { if (_glfw.wl.dataOffers[i].id == id) {
_glfw.wl.dataOffers[i].dnd_action = action; _glfw.wl.dataOffers[i].dnd_action = action;
@@ -1664,7 +1676,7 @@ static const struct zwp_primary_selection_offer_v1_listener primary_selection_of
.offer = handle_primary_selection_offer_mimetype, .offer = handle_primary_selection_offer_mimetype,
}; };
static void handle_data_offer(void *data, struct wl_data_device *wl_data_device, struct wl_data_offer *id) { static void handle_data_offer(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, struct wl_data_offer *id) {
size_t smallest_idx = SIZE_MAX, pos = 0; size_t smallest_idx = SIZE_MAX, pos = 0;
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].idx && _glfw.wl.dataOffers[i].idx < smallest_idx) { if (_glfw.wl.dataOffers[i].idx && _glfw.wl.dataOffers[i].idx < smallest_idx) {
@@ -1685,7 +1697,7 @@ end:
wl_data_offer_add_listener(id, &data_offer_listener, NULL); wl_data_offer_add_listener(id, &data_offer_listener, NULL);
} }
static void handle_primary_selection_offer(void *data, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device_v1, struct zwp_primary_selection_offer_v1 *id) { static void handle_primary_selection_offer(void *data UNUSED, struct zwp_primary_selection_device_v1 *zwp_primary_selection_device_v1 UNUSED, struct zwp_primary_selection_offer_v1 *id) {
size_t smallest_idx = SIZE_MAX, pos = 0; size_t smallest_idx = SIZE_MAX, pos = 0;
for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.primarySelectionOffers); i++) {
if (_glfw.wl.primarySelectionOffers[i].idx && _glfw.wl.primarySelectionOffers[i].idx < smallest_idx) { if (_glfw.wl.primarySelectionOffers[i].idx && _glfw.wl.primarySelectionOffers[i].idx < smallest_idx) {
@@ -1706,7 +1718,7 @@ end:
zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, NULL); zwp_primary_selection_offer_v1_add_listener(id, &primary_selection_offer_listener, NULL);
} }
static void drag_enter(void *data, struct wl_data_device *wl_data_device, uint32_t serial, struct wl_surface *surface, wl_fixed_t x, wl_fixed_t y, struct wl_data_offer *id) { static void drag_enter(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t serial, struct wl_surface *surface, wl_fixed_t x UNUSED, wl_fixed_t y UNUSED, struct wl_data_offer *id) {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].id == id) { if (_glfw.wl.dataOffers[i].id == id) {
_glfw.wl.dataOffers[i].offer_type = DRAG_AND_DROP; _glfw.wl.dataOffers[i].offer_type = DRAG_AND_DROP;
@@ -1720,7 +1732,7 @@ static void drag_enter(void *data, struct wl_data_device *wl_data_device, uint32
prune_unclaimed_data_offers(); prune_unclaimed_data_offers();
} }
static void drag_leave(void *data, struct wl_data_device *wl_data_device) { static void drag_leave(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED) {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) { if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
wl_data_offer_destroy(_glfw.wl.dataOffers[i].id); wl_data_offer_destroy(_glfw.wl.dataOffers[i].id);
@@ -1729,7 +1741,7 @@ static void drag_leave(void *data, struct wl_data_device *wl_data_device) {
} }
} }
static void drop(void *data, struct wl_data_device *wl_data_device) { static void drop(void *data, struct wl_data_device *wl_data_device UNUSED) {
for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) { for (size_t i = 0; i < arraysz(_glfw.wl.dataOffers); i++) {
if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) { if (_glfw.wl.dataOffers[i].offer_type == DRAG_AND_DROP) {
char *uri_list = read_data_offer(_glfw.wl.dataOffers[i].id, URI_LIST_MIME); char *uri_list = read_data_offer(_glfw.wl.dataOffers[i].id, URI_LIST_MIME);
@@ -1761,10 +1773,10 @@ static void drop(void *data, struct wl_data_device *wl_data_device) {
} }
} }
static void motion(void *data, struct wl_data_device *wl_data_device, uint32_t time, wl_fixed_t x, wl_fixed_t y) { static void motion(void *data UNUSED, struct wl_data_device *wl_data_device UNUSED, uint32_t time UNUSED, wl_fixed_t x UNUSED, wl_fixed_t y UNUSED) {
} }
const static struct wl_data_device_listener data_device_listener = { static const struct wl_data_device_listener data_device_listener = {
.data_offer = handle_data_offer, .data_offer = handle_data_offer,
.selection = mark_selection_offer, .selection = mark_selection_offer,
.enter = drag_enter, .enter = drag_enter,
@@ -1773,7 +1785,7 @@ const static struct wl_data_device_listener data_device_listener = {
.leave = drag_leave, .leave = drag_leave,
}; };
const static struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = { static const struct zwp_primary_selection_device_v1_listener primary_selection_device_listener = {
.data_offer = handle_primary_selection_offer, .data_offer = handle_primary_selection_offer,
.selection = mark_primary_selection_offer, .selection = mark_primary_selection_offer,
}; };
@@ -1824,7 +1836,7 @@ static inline bool _glfwEnsureDataDevice(void) {
if (!_glfw.wl.dataDevice) if (!_glfw.wl.dataDevice)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Cannot use clipboard, failed to create data device"); "Wayland: Cannot use clipboard, failed to create data device");
return false; return false;
} }
} }
@@ -1853,7 +1865,7 @@ void _glfwPlatformSetClipboardString(const char* string)
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "STRING"); wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "STRING");
wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "UTF8_STRING"); wl_data_source_offer(_glfw.wl.dataSourceForClipboard, "UTF8_STRING");
struct wl_callback *callback = wl_display_sync(_glfw.wl.display); struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
const static struct wl_callback_listener clipboard_copy_callback_listener = {.done = clipboard_copy_callback_done}; static const struct wl_callback_listener clipboard_copy_callback_listener = {.done = clipboard_copy_callback_done};
wl_callback_add_listener(callback, &clipboard_copy_callback_listener, _glfw.wl.dataSourceForClipboard); wl_callback_add_listener(callback, &clipboard_copy_callback_listener, _glfw.wl.dataSourceForClipboard);
} }
@@ -1902,7 +1914,7 @@ void _glfwPlatformSetPrimarySelectionString(const char* string)
zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "STRING"); zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "STRING");
zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "UTF8_STRING"); zwp_primary_selection_source_v1_offer(_glfw.wl.dataSourceForPrimarySelection, "UTF8_STRING");
struct wl_callback *callback = wl_display_sync(_glfw.wl.display); struct wl_callback *callback = wl_display_sync(_glfw.wl.display);
const static struct wl_callback_listener primary_selection_copy_callback_listener = {.done = primary_selection_copy_callback_done}; static const struct wl_callback_listener primary_selection_copy_callback_listener = {.done = primary_selection_copy_callback_done};
wl_callback_add_listener(callback, &primary_selection_copy_callback_listener, _glfw.wl.dataSourceForPrimarySelection); wl_callback_add_listener(callback, &primary_selection_copy_callback_listener, _glfw.wl.dataSourceForPrimarySelection);
} }
@@ -1992,7 +2004,7 @@ _glfwPlatformUpdateIMEState(_GLFWwindow *w, int which, int a, int b, int c, int
} }
static void static void
frame_handle_redraw(void *data, struct wl_callback *callback, uint32_t time) { frame_handle_redraw(void *data, struct wl_callback *callback, uint32_t time UNUSED) {
_GLFWwindow* window = (_GLFWwindow*) data; _GLFWwindow* window = (_GLFWwindow*) data;
if (callback == window->wl.frameCallbackData.current_wl_callback) { if (callback == window->wl.frameCallbackData.current_wl_callback) {
window->wl.frameCallbackData.callback(window->wl.frameCallbackData.id); window->wl.frameCallbackData.callback(window->wl.frameCallbackData.id);
@@ -2001,6 +2013,7 @@ frame_handle_redraw(void *data, struct wl_callback *callback, uint32_t time) {
wl_callback_destroy(callback); wl_callback_destroy(callback);
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW native API ////// ////// GLFW native API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////

174
glfw/x11_init.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 X11 - www.glfw.org // GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#define _GNU_SOURCE #define _GNU_SOURCE
#include "internal.h" #include "internal.h"
@@ -46,10 +48,9 @@ static Atom getSupportedAtom(Atom* supportedAtoms,
unsigned long atomCount, unsigned long atomCount,
const char* atomName) const char* atomName)
{ {
unsigned long i;
const Atom atom = XInternAtom(_glfw.x11.display, atomName, False); const Atom atom = XInternAtom(_glfw.x11.display, atomName, False);
for (i = 0; i < atomCount; i++) for (unsigned long i = 0; i < atomCount; i++)
{ {
if (supportedAtoms[i] == atom) if (supportedAtoms[i] == atom)
return atom; return atom;
@@ -62,18 +63,12 @@ static Atom getSupportedAtom(Atom* supportedAtoms,
// //
static void detectEWMH(void) static void detectEWMH(void)
{ {
// First we read the _NET_SUPPORTING_WM_CHECK property on the root window
Window* windowFromRoot = NULL; Window* windowFromRoot = NULL;
Window* windowFromChild = NULL;
// First we need a couple of atoms
const Atom supportingWmCheck =
XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
const Atom wmSupported =
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
// Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window // Then we look for the _NET_SUPPORTING_WM_CHECK property of the root window
if (!_glfwGetWindowPropertyX11(_glfw.x11.root, if (!_glfwGetWindowPropertyX11(_glfw.x11.root,
supportingWmCheck, _glfw.x11.NET_SUPPORTING_WM_CHECK,
XA_WINDOW, XA_WINDOW,
(unsigned char**) &windowFromRoot)) (unsigned char**) &windowFromRoot))
{ {
@@ -82,10 +77,12 @@ static void detectEWMH(void)
_glfwGrabErrorHandlerX11(); _glfwGrabErrorHandlerX11();
// It should be the ID of a child window (of the root) // If it exists, it should be the XID of a top-level window
// Then we look for the same property on the child window // Then we look for the same property on that window
Window* windowFromChild = NULL;
if (!_glfwGetWindowPropertyX11(*windowFromRoot, if (!_glfwGetWindowPropertyX11(*windowFromRoot,
supportingWmCheck, _glfw.x11.NET_SUPPORTING_WM_CHECK,
XA_WINDOW, XA_WINDOW,
(unsigned char**) &windowFromChild)) (unsigned char**) &windowFromChild))
{ {
@@ -95,7 +92,7 @@ static void detectEWMH(void)
_glfwReleaseErrorHandlerX11(); _glfwReleaseErrorHandlerX11();
// It should be the ID of that same child window // If the property exists, it should contain the XID of the window
if (*windowFromRoot != *windowFromChild) if (*windowFromRoot != *windowFromChild)
{ {
XFree(windowFromRoot); XFree(windowFromRoot);
@@ -107,18 +104,20 @@ static void detectEWMH(void)
XFree(windowFromChild); XFree(windowFromChild);
// We are now fairly sure that an EWMH-compliant window manager is running // We are now fairly sure that an EWMH-compliant window manager is running
// We can now start querying the WM about what features it supports by
// looking in the _NET_SUPPORTED property on the root window
// It should contain a list of supported EWMH protocol and state atoms
Atom* supportedAtoms; Atom* supportedAtoms = NULL;
unsigned long atomCount; const unsigned long atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
_glfw.x11.NET_SUPPORTED,
// Now we need to check the _NET_SUPPORTED property of the root window
// It should be a list of supported WM protocol and state atoms
atomCount = _glfwGetWindowPropertyX11(_glfw.x11.root,
wmSupported,
XA_ATOM, XA_ATOM,
(unsigned char**) &supportedAtoms); (unsigned char**) &supportedAtoms);
if (!supportedAtoms)
return;
// See which of the atoms we support that are supported by the WM // See which of the atoms we support that are supported by the WM
_glfw.x11.NET_WM_STATE = _glfw.x11.NET_WM_STATE =
getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE"); getSupportedAtom(supportedAtoms, atomCount, "_NET_WM_STATE");
_glfw.x11.NET_WM_STATE_ABOVE = _glfw.x11.NET_WM_STATE_ABOVE =
@@ -148,8 +147,7 @@ static void detectEWMH(void)
_glfw.x11.NET_REQUEST_FRAME_EXTENTS = _glfw.x11.NET_REQUEST_FRAME_EXTENTS =
getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS"); getSupportedAtom(supportedAtoms, atomCount, "_NET_REQUEST_FRAME_EXTENTS");
if (supportedAtoms) XFree(supportedAtoms);
XFree(supportedAtoms);
} }
// Look for and initialize supported X11 extensions // Look for and initialize supported X11 extensions
@@ -159,14 +157,10 @@ static bool initExtensions(void)
_glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1"); _glfw.x11.vidmode.handle = _glfw_dlopen("libXxf86vm.so.1");
if (_glfw.x11.vidmode.handle) if (_glfw.x11.vidmode.handle)
{ {
_glfw.x11.vidmode.QueryExtension = (PFN_XF86VidModeQueryExtension) glfw_dlsym(_glfw.x11.vidmode.QueryExtension, _glfw.x11.vidmode.handle, "XF86VidModeQueryExtension");
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeQueryExtension"); glfw_dlsym(_glfw.x11.vidmode.GetGammaRamp, _glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp");
_glfw.x11.vidmode.GetGammaRamp = (PFN_XF86VidModeGetGammaRamp) glfw_dlsym(_glfw.x11.vidmode.SetGammaRamp, _glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRamp"); glfw_dlsym(_glfw.x11.vidmode.GetGammaRampSize, _glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
_glfw.x11.vidmode.SetGammaRamp = (PFN_XF86VidModeSetGammaRamp)
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeSetGammaRamp");
_glfw.x11.vidmode.GetGammaRampSize = (PFN_XF86VidModeGetGammaRampSize)
_glfw_dlsym(_glfw.x11.vidmode.handle, "XF86VidModeGetGammaRampSize");
_glfw.x11.vidmode.available = _glfw.x11.vidmode.available =
XF86VidModeQueryExtension(_glfw.x11.display, XF86VidModeQueryExtension(_glfw.x11.display,
@@ -181,10 +175,8 @@ static bool initExtensions(void)
#endif #endif
if (_glfw.x11.xi.handle) if (_glfw.x11.xi.handle)
{ {
_glfw.x11.xi.QueryVersion = (PFN_XIQueryVersion) glfw_dlsym(_glfw.x11.xi.QueryVersion, _glfw.x11.xi.handle, "XIQueryVersion");
_glfw_dlsym(_glfw.x11.xi.handle, "XIQueryVersion"); glfw_dlsym(_glfw.x11.xi.SelectEvents, _glfw.x11.xi.handle, "XISelectEvents");
_glfw.x11.xi.SelectEvents = (PFN_XISelectEvents)
_glfw_dlsym(_glfw.x11.xi.handle, "XISelectEvents");
if (XQueryExtension(_glfw.x11.display, if (XQueryExtension(_glfw.x11.display,
"XInputExtension", "XInputExtension",
@@ -211,42 +203,24 @@ static bool initExtensions(void)
#endif #endif
if (_glfw.x11.randr.handle) if (_glfw.x11.randr.handle)
{ {
_glfw.x11.randr.AllocGamma = (PFN_XRRAllocGamma) glfw_dlsym(_glfw.x11.randr.AllocGamma, _glfw.x11.randr.handle, "XRRAllocGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRAllocGamma"); glfw_dlsym(_glfw.x11.randr.FreeGamma, _glfw.x11.randr.handle, "XRRFreeGamma");
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) glfw_dlsym(_glfw.x11.randr.FreeCrtcInfo, _glfw.x11.randr.handle, "XRRFreeCrtcInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); glfw_dlsym(_glfw.x11.randr.FreeGamma, _glfw.x11.randr.handle, "XRRFreeGamma");
_glfw.x11.randr.FreeCrtcInfo = (PFN_XRRFreeCrtcInfo) glfw_dlsym(_glfw.x11.randr.FreeOutputInfo, _glfw.x11.randr.handle, "XRRFreeOutputInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeCrtcInfo"); glfw_dlsym(_glfw.x11.randr.FreeScreenResources, _glfw.x11.randr.handle, "XRRFreeScreenResources");
_glfw.x11.randr.FreeGamma = (PFN_XRRFreeGamma) glfw_dlsym(_glfw.x11.randr.GetCrtcGamma, _glfw.x11.randr.handle, "XRRGetCrtcGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeGamma"); glfw_dlsym(_glfw.x11.randr.GetCrtcGammaSize, _glfw.x11.randr.handle, "XRRGetCrtcGammaSize");
_glfw.x11.randr.FreeOutputInfo = (PFN_XRRFreeOutputInfo) glfw_dlsym(_glfw.x11.randr.GetCrtcInfo, _glfw.x11.randr.handle, "XRRGetCrtcInfo");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeOutputInfo"); glfw_dlsym(_glfw.x11.randr.GetOutputInfo, _glfw.x11.randr.handle, "XRRGetOutputInfo");
_glfw.x11.randr.FreeScreenResources = (PFN_XRRFreeScreenResources) glfw_dlsym(_glfw.x11.randr.GetOutputPrimary, _glfw.x11.randr.handle, "XRRGetOutputPrimary");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRFreeScreenResources"); glfw_dlsym(_glfw.x11.randr.GetScreenResourcesCurrent, _glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
_glfw.x11.randr.GetCrtcGamma = (PFN_XRRGetCrtcGamma) glfw_dlsym(_glfw.x11.randr.QueryExtension, _glfw.x11.randr.handle, "XRRQueryExtension");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGamma"); glfw_dlsym(_glfw.x11.randr.QueryVersion, _glfw.x11.randr.handle, "XRRQueryVersion");
_glfw.x11.randr.GetCrtcGammaSize = (PFN_XRRGetCrtcGammaSize) glfw_dlsym(_glfw.x11.randr.SelectInput, _glfw.x11.randr.handle, "XRRSelectInput");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcGammaSize"); glfw_dlsym(_glfw.x11.randr.SetCrtcConfig, _glfw.x11.randr.handle, "XRRSetCrtcConfig");
_glfw.x11.randr.GetCrtcInfo = (PFN_XRRGetCrtcInfo) glfw_dlsym(_glfw.x11.randr.SetCrtcGamma, _glfw.x11.randr.handle, "XRRSetCrtcGamma");
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetCrtcInfo"); glfw_dlsym(_glfw.x11.randr.UpdateConfiguration, _glfw.x11.randr.handle, "XRRUpdateConfiguration");
_glfw.x11.randr.GetOutputInfo = (PFN_XRRGetOutputInfo)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputInfo");
_glfw.x11.randr.GetOutputPrimary = (PFN_XRRGetOutputPrimary)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetOutputPrimary");
_glfw.x11.randr.GetScreenResourcesCurrent = (PFN_XRRGetScreenResourcesCurrent)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRGetScreenResourcesCurrent");
_glfw.x11.randr.QueryExtension = (PFN_XRRQueryExtension)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryExtension");
_glfw.x11.randr.QueryVersion = (PFN_XRRQueryVersion)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRQueryVersion");
_glfw.x11.randr.SelectInput = (PFN_XRRSelectInput)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSelectInput");
_glfw.x11.randr.SetCrtcConfig = (PFN_XRRSetCrtcConfig)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcConfig");
_glfw.x11.randr.SetCrtcGamma = (PFN_XRRSetCrtcGamma)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRSetCrtcGamma");
_glfw.x11.randr.UpdateConfiguration = (PFN_XRRUpdateConfiguration)
_glfw_dlsym(_glfw.x11.randr.handle, "XRRUpdateConfiguration");
if (XRRQueryExtension(_glfw.x11.display, if (XRRQueryExtension(_glfw.x11.display,
&_glfw.x11.randr.eventBase, &_glfw.x11.randr.eventBase,
@@ -303,12 +277,9 @@ static bool initExtensions(void)
#endif #endif
if (_glfw.x11.xcursor.handle) if (_glfw.x11.xcursor.handle)
{ {
_glfw.x11.xcursor.ImageCreate = (PFN_XcursorImageCreate) glfw_dlsym(_glfw.x11.xcursor.ImageCreate, _glfw.x11.xcursor.handle, "XcursorImageCreate");
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageCreate"); glfw_dlsym(_glfw.x11.xcursor.ImageDestroy, _glfw.x11.xcursor.handle, "XcursorImageDestroy");
_glfw.x11.xcursor.ImageDestroy = (PFN_XcursorImageDestroy) glfw_dlsym(_glfw.x11.xcursor.ImageLoadCursor, _glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageDestroy");
_glfw.x11.xcursor.ImageLoadCursor = (PFN_XcursorImageLoadCursor)
_glfw_dlsym(_glfw.x11.xcursor.handle, "XcursorImageLoadCursor");
} }
#if defined(__CYGWIN__) #if defined(__CYGWIN__)
@@ -318,12 +289,9 @@ static bool initExtensions(void)
#endif #endif
if (_glfw.x11.xinerama.handle) if (_glfw.x11.xinerama.handle)
{ {
_glfw.x11.xinerama.IsActive = (PFN_XineramaIsActive) glfw_dlsym(_glfw.x11.xinerama.IsActive, _glfw.x11.xinerama.handle, "XineramaIsActive");
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaIsActive"); glfw_dlsym(_glfw.x11.xinerama.QueryExtension, _glfw.x11.xinerama.handle, "XineramaQueryExtension");
_glfw.x11.xinerama.QueryExtension = (PFN_XineramaQueryExtension) glfw_dlsym(_glfw.x11.xinerama.QueryScreens, _glfw.x11.xinerama.handle, "XineramaQueryScreens");
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryExtension");
_glfw.x11.xinerama.QueryScreens = (PFN_XineramaQueryScreens)
_glfw_dlsym(_glfw.x11.xinerama.handle, "XineramaQueryScreens");
if (XineramaQueryExtension(_glfw.x11.display, if (XineramaQueryExtension(_glfw.x11.display,
&_glfw.x11.xinerama.major, &_glfw.x11.xinerama.major,
@@ -341,12 +309,9 @@ static bool initExtensions(void)
#endif #endif
if (_glfw.x11.xrender.handle) if (_glfw.x11.xrender.handle)
{ {
_glfw.x11.xrender.QueryExtension = (PFN_XRenderQueryExtension) glfw_dlsym(_glfw.x11.xrender.QueryExtension, _glfw.x11.xrender.handle, "XRenderQueryExtension");
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryExtension"); glfw_dlsym(_glfw.x11.xrender.QueryVersion, _glfw.x11.xrender.handle, "XRenderQueryVersion");
_glfw.x11.xrender.QueryVersion = (PFN_XRenderQueryVersion) glfw_dlsym(_glfw.x11.xrender.FindVisualFormat, _glfw.x11.xrender.handle, "XRenderFindVisualFormat");
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderQueryVersion");
_glfw.x11.xrender.FindVisualFormat = (PFN_XRenderFindVisualFormat)
_glfw_dlsym(_glfw.x11.xrender.handle, "XRenderFindVisualFormat");
if (XRenderQueryExtension(_glfw.x11.display, if (XRenderQueryExtension(_glfw.x11.display,
&_glfw.x11.xrender.errorBase, &_glfw.x11.xrender.errorBase,
@@ -387,9 +352,6 @@ static bool initExtensions(void)
if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return false; if (!glfw_xkb_update_x11_keyboard_id(&_glfw.x11.xkb)) return false;
if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return false; if (!glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL)) return false;
// Detect whether an EWMH-conformant window manager is running
detectEWMH();
// String format atoms // String format atoms
_glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False); _glfw.x11.NULL_ = XInternAtom(_glfw.x11.display, "NULL", False);
_glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False); _glfw.x11.UTF8_STRING = XInternAtom(_glfw.x11.display, "UTF8_STRING", False);
@@ -433,6 +395,10 @@ static bool initExtensions(void)
XInternAtom(_glfw.x11.display, "WM_STATE", False); XInternAtom(_glfw.x11.display, "WM_STATE", False);
_glfw.x11.WM_DELETE_WINDOW = _glfw.x11.WM_DELETE_WINDOW =
XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False); XInternAtom(_glfw.x11.display, "WM_DELETE_WINDOW", False);
_glfw.x11.NET_SUPPORTED =
XInternAtom(_glfw.x11.display, "_NET_SUPPORTED", False);
_glfw.x11.NET_SUPPORTING_WM_CHECK =
XInternAtom(_glfw.x11.display, "_NET_SUPPORTING_WM_CHECK", False);
_glfw.x11.NET_WM_ICON = _glfw.x11.NET_WM_ICON =
XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False); XInternAtom(_glfw.x11.display, "_NET_WM_ICON", False);
_glfw.x11.NET_WM_PING = _glfw.x11.NET_WM_PING =
@@ -457,6 +423,9 @@ static bool initExtensions(void)
_glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False); _glfw.x11.NET_WM_CM_Sx = XInternAtom(_glfw.x11.display, name, False);
} }
// Detect whether an EWMH-conformant window manager is running
detectEWMH();
return true; return true;
} }
@@ -536,7 +505,7 @@ static Window createHelperWindow(void)
// X error handler // X error handler
// //
static int errorHandler(Display *display, XErrorEvent* event) static int errorHandler(Display *display UNUSED, XErrorEvent* event)
{ {
_glfw.x11.errorCode = event->error_code; _glfw.x11.errorCode = event->error_code;
return 0; return 0;
@@ -611,6 +580,7 @@ Cursor _glfwCreateCursorX11(const GLFWimage* image, int xhot, int yhot)
return cursor; return cursor;
} }
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
@@ -620,13 +590,6 @@ int _glfwPlatformInit(void)
XInitThreads(); XInitThreads();
XrmInitialize(); XrmInitialize();
if (pipe2(_glfw.x11.eventLoopData.wakeupFds, O_CLOEXEC | O_NONBLOCK) != 0)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: failed to create self pipe");
return false;
}
_glfw.x11.display = XOpenDisplay(NULL); _glfw.x11.display = XOpenDisplay(NULL);
if (!_glfw.x11.display) if (!_glfw.x11.display)
{ {
@@ -645,7 +608,10 @@ int _glfwPlatformInit(void)
return false; return false;
} }
initPollData(&_glfw.x11.eventLoopData, _glfw.x11.eventLoopData.wakeupFds[0], ConnectionNumber(_glfw.x11.display)); if (!initPollData(&_glfw.x11.eventLoopData, ConnectionNumber(_glfw.x11.display))) {
_glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Failed to initialize event loop data");
}
glfw_dbus_init(&_glfw.x11.dbus, &_glfw.x11.eventLoopData); glfw_dbus_init(&_glfw.x11.dbus, &_glfw.x11.eventLoopData);
_glfw.x11.screen = DefaultScreen(_glfw.x11.display); _glfw.x11.screen = DefaultScreen(_glfw.x11.display);
@@ -754,7 +720,7 @@ void _glfwPlatformTerminate(void)
#if defined(__linux__) #if defined(__linux__)
_glfwTerminateJoysticksLinux(); _glfwTerminateJoysticksLinux();
#endif #endif
closeFds(_glfw.x11.eventLoopData.wakeupFds, sizeof(_glfw.x11.eventLoopData.wakeupFds)/sizeof(_glfw.x11.eventLoopData.wakeupFds[0])); finalizePollData(&_glfw.x11.eventLoopData);
} }
const char* _glfwPlatformGetVersionString(void) const char* _glfwPlatformGetVersionString(void)

96
glfw/x11_monitor.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 X11 - www.glfw.org // GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#include "internal.h" #include "internal.h"
@@ -54,9 +56,7 @@ static int calculateRefreshRate(const XRRModeInfo* mi)
// //
static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id) static const XRRModeInfo* getModeInfo(const XRRScreenResources* sr, RRMode id)
{ {
int i; for (int i = 0; i < sr->nmode; i++)
for (i = 0; i < sr->nmode; i++)
{ {
if (sr->modes[i].id == id) if (sr->modes[i].id == id)
return sr->modes + i; return sr->modes + i;
@@ -102,7 +102,7 @@ void _glfwPollMonitorsX11(void)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
int i, j, disconnectedCount, screenCount = 0; int disconnectedCount, screenCount = 0;
_GLFWmonitor** disconnected = NULL; _GLFWmonitor** disconnected = NULL;
XineramaScreenInfo* screens = NULL; XineramaScreenInfo* screens = NULL;
XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display,
@@ -122,14 +122,11 @@ void _glfwPollMonitorsX11(void)
_glfw.monitorCount * sizeof(_GLFWmonitor*)); _glfw.monitorCount * sizeof(_GLFWmonitor*));
} }
for (i = 0; i < sr->noutput; i++) for (int i = 0; i < sr->noutput; i++)
{ {
int type, widthMM, heightMM; int j, type, widthMM, heightMM;
XRROutputInfo* oi;
XRRCrtcInfo* ci;
_GLFWmonitor* monitor;
oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]); XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, sr->outputs[i]);
if (oi->connection != RR_Connected || oi->crtc == None) if (oi->connection != RR_Connected || oi->crtc == None)
{ {
XRRFreeOutputInfo(oi); XRRFreeOutputInfo(oi);
@@ -152,7 +149,7 @@ void _glfwPollMonitorsX11(void)
continue; continue;
} }
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, oi->crtc);
if (!ci) if (!ci)
{ {
XRRFreeOutputInfo(oi); XRRFreeOutputInfo(oi);
@@ -169,7 +166,7 @@ void _glfwPollMonitorsX11(void)
heightMM = oi->mm_height; heightMM = oi->mm_height;
} }
monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM); _GLFWmonitor* monitor = _glfwAllocMonitor(oi->name, widthMM, heightMM);
monitor->x11.output = sr->outputs[i]; monitor->x11.output = sr->outputs[i];
monitor->x11.crtc = oi->crtc; monitor->x11.crtc = oi->crtc;
@@ -177,8 +174,8 @@ void _glfwPollMonitorsX11(void)
{ {
if (screens[j].x_org == ci->x && if (screens[j].x_org == ci->x &&
screens[j].y_org == ci->y && screens[j].y_org == ci->y &&
screens[j].width == ci->width && screens[j].width == (short int)ci->width &&
screens[j].height == ci->height) screens[j].height == (short int)ci->height)
{ {
monitor->x11.index = j; monitor->x11.index = j;
break; break;
@@ -201,7 +198,7 @@ void _glfwPollMonitorsX11(void)
if (screens) if (screens)
XFree(screens); XFree(screens);
for (i = 0; i < disconnectedCount; i++) for (int i = 0; i < disconnectedCount; i++)
{ {
if (disconnected[i]) if (disconnected[i])
_glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0); _glfwInputMonitor(disconnected[i], GLFW_DISCONNECTED, 0);
@@ -226,24 +223,19 @@ void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
XRRScreenResources* sr;
XRRCrtcInfo* ci;
XRROutputInfo* oi;
GLFWvidmode current; GLFWvidmode current;
const GLFWvidmode* best;
RRMode native = None; RRMode native = None;
int i;
best = _glfwChooseVideoMode(monitor, desired); const GLFWvidmode* best = _glfwChooseVideoMode(monitor, desired);
_glfwPlatformGetVideoMode(monitor, &current); _glfwPlatformGetVideoMode(monitor, &current);
if (_glfwCompareVideoModes(&current, best) == 0) if (_glfwCompareVideoModes(&current, best) == 0)
return; return;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output); XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
for (i = 0; i < oi->nmode; i++) for (int i = 0; i < oi->nmode; i++)
{ {
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
if (!modeIsGood(mi)) if (!modeIsGood(mi))
@@ -284,14 +276,11 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
XRRScreenResources* sr;
XRRCrtcInfo* ci;
if (monitor->x11.oldMode == None) if (monitor->x11.oldMode == None)
return; return;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
XRRSetCrtcConfig(_glfw.x11.display, XRRSetCrtcConfig(_glfw.x11.display,
sr, monitor->x11.crtc, sr, monitor->x11.crtc,
@@ -314,7 +303,7 @@ void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor)
////// GLFW platform API ////// ////// GLFW platform API //////
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor) void _glfwPlatformFreeMonitor(_GLFWmonitor* monitor UNUSED)
{ {
} }
@@ -322,11 +311,9 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
XRRScreenResources* sr;
XRRCrtcInfo* ci;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
if (ci) if (ci)
{ {
if (xpos) if (xpos)
@@ -340,7 +327,7 @@ void _glfwPlatformGetMonitorPos(_GLFWmonitor* monitor, int* xpos, int* ypos)
} }
} }
void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor, void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor UNUSED,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
@@ -349,17 +336,15 @@ void _glfwPlatformGetMonitorContentScale(_GLFWmonitor* monitor,
*yscale = _glfw.x11.contentScaleY; *yscale = _glfw.x11.contentScaleY;
} }
void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int *width, int *height) void _glfwPlatformGetMonitorWorkarea(_GLFWmonitor* monitor, int* xpos, int* ypos, int* width, int* height)
{ {
int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0; int areaX = 0, areaY = 0, areaWidth = 0, areaHeight = 0;
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
XRRScreenResources* sr;
XRRCrtcInfo* ci;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
areaX = ci->x; areaX = ci->x;
areaY = ci->y; areaY = ci->y;
@@ -451,24 +436,20 @@ GLFWvidmode* _glfwPlatformGetVideoModes(_GLFWmonitor* monitor, int* count)
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
int i, j; XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
XRRScreenResources* sr; XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
XRRCrtcInfo* ci; XRROutputInfo* oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
XRROutputInfo* oi;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
oi = XRRGetOutputInfo(_glfw.x11.display, sr, monitor->x11.output);
result = calloc(oi->nmode, sizeof(GLFWvidmode)); result = calloc(oi->nmode, sizeof(GLFWvidmode));
for (i = 0; i < oi->nmode; i++) for (int i = 0; i < oi->nmode; i++)
{ {
const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]); const XRRModeInfo* mi = getModeInfo(sr, oi->modes[i]);
if (!modeIsGood(mi)) if (!modeIsGood(mi))
continue; continue;
const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci); const GLFWvidmode mode = vidmodeFromModeInfo(mi, ci);
int j;
for (j = 0; j < *count; j++) for (j = 0; j < *count; j++)
{ {
@@ -502,11 +483,9 @@ void _glfwPlatformGetVideoMode(_GLFWmonitor* monitor, GLFWvidmode* mode)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.monitorBroken)
{ {
XRRScreenResources* sr;
XRRCrtcInfo* ci;
sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root); XRRScreenResources* sr = XRRGetScreenResourcesCurrent(_glfw.x11.display, _glfw.x11.root);
ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc); XRRCrtcInfo* ci = XRRGetCrtcInfo(_glfw.x11.display, sr, monitor->x11.crtc);
if (ci) { if (ci) {
const XRRModeInfo* mi = getModeInfo(sr, ci->mode); const XRRModeInfo* mi = getModeInfo(sr, ci->mode);
@@ -570,7 +549,7 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
{ {
if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken) if (_glfw.x11.randr.available && !_glfw.x11.randr.gammaBroken)
{ {
if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != ramp->size) if (XRRGetCrtcGammaSize(_glfw.x11.display, monitor->x11.crtc) != (int)ramp->size)
{ {
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Gamma ramp size must match current ramp size"); "X11: Gamma ramp size must match current ramp size");
@@ -595,7 +574,8 @@ void _glfwPlatformSetGammaRamp(_GLFWmonitor* monitor, const GLFWgammaramp* ramp)
(unsigned short*) ramp->green, (unsigned short*) ramp->green,
(unsigned short*) ramp->blue); (unsigned short*) ramp->blue);
} }
else { else
{
_glfwInputError(GLFW_PLATFORM_ERROR, _glfwInputError(GLFW_PLATFORM_ERROR,
"X11: Gamma ramp access not supported by server"); "X11: Gamma ramp access not supported by server");
} }

27
glfw/x11_platform.h vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 X11 - www.glfw.org // GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -182,11 +182,11 @@ typedef struct _GLFWwindowX11
Colormap colormap; Colormap colormap;
Window handle; Window handle;
bool iconified; bool iconified;
bool maximized; bool maximized;
// Whether the visual supports framebuffer transparency // Whether the visual supports framebuffer transparency
bool transparent; bool transparent;
// Cached position and size used to filter out duplicate events // Cached position and size used to filter out duplicate events
int width, height; int width, height;
@@ -227,6 +227,8 @@ typedef struct _GLFWlibraryX11
_GLFWwindow* disabledCursorWindow; _GLFWwindow* disabledCursorWindow;
// Window manager atoms // Window manager atoms
Atom NET_SUPPORTED;
Atom NET_SUPPORTING_WM_CHECK;
Atom WM_PROTOCOLS; Atom WM_PROTOCOLS;
Atom WM_STATE; Atom WM_STATE;
Atom WM_DELETE_WINDOW; Atom WM_DELETE_WINDOW;
@@ -284,14 +286,14 @@ typedef struct _GLFWlibraryX11
Atom RESOURCE_MANAGER; Atom RESOURCE_MANAGER;
struct { struct {
bool available; bool available;
void* handle; void* handle;
int eventBase; int eventBase;
int errorBase; int errorBase;
int major; int major;
int minor; int minor;
bool gammaBroken; bool gammaBroken;
bool monitorBroken; bool monitorBroken;
PFN_XRRAllocGamma AllocGamma; PFN_XRRAllocGamma AllocGamma;
PFN_XRRFreeCrtcInfo FreeCrtcInfo; PFN_XRRFreeCrtcInfo FreeCrtcInfo;
PFN_XRRFreeGamma FreeGamma; PFN_XRRFreeGamma FreeGamma;
@@ -336,7 +338,7 @@ typedef struct _GLFWlibraryX11
} xcursor; } xcursor;
struct { struct {
bool available; bool available;
void* handle; void* handle;
int major; int major;
int minor; int minor;
@@ -346,7 +348,7 @@ typedef struct _GLFWlibraryX11
} xinerama; } xinerama;
struct { struct {
bool available; bool available;
void* handle; void* handle;
int eventBase; int eventBase;
int errorBase; int errorBase;
@@ -357,7 +359,7 @@ typedef struct _GLFWlibraryX11
} vidmode; } vidmode;
struct { struct {
bool available; bool available;
void* handle; void* handle;
int majorOpcode; int majorOpcode;
int eventBase; int eventBase;
@@ -369,7 +371,7 @@ typedef struct _GLFWlibraryX11
} xi; } xi;
struct { struct {
bool available; bool available;
void* handle; void* handle;
int major; int major;
int minor; int minor;
@@ -406,6 +408,7 @@ typedef struct _GLFWcursorX11
} _GLFWcursorX11; } _GLFWcursorX11;
void _glfwPollMonitorsX11(void); void _glfwPollMonitorsX11(void);
void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired); void _glfwSetVideoModeX11(_GLFWmonitor* monitor, const GLFWvidmode* desired);
void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor); void _glfwRestoreVideoModeX11(_GLFWmonitor* monitor);

124
glfw/x11_window.c vendored
View File

@@ -1,8 +1,8 @@
//======================================================================== //========================================================================
// GLFW 3.3 X11 - www.glfw.org // GLFW 3.4 X11 - www.glfw.org
//------------------------------------------------------------------------ //------------------------------------------------------------------------
// Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2002-2006 Marcus Geelnard
// Copyright (c) 2006-2016 Camilla Löwy <elmindreda@glfw.org> // Copyright (c) 2006-2019 Camilla Löwy <elmindreda@glfw.org>
// //
// This software is provided 'as-is', without any express or implied // This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages // warranty. In no event will the authors be held liable for any damages
@@ -24,6 +24,8 @@
// distribution. // distribution.
// //
//======================================================================== //========================================================================
// It is fine to use C99 in this file because it will not be built with VS
//========================================================================
#define _GNU_SOURCE #define _GNU_SOURCE
#include "internal.h" #include "internal.h"
@@ -51,6 +53,7 @@
#define _GLFW_XDND_VERSION 5 #define _GLFW_XDND_VERSION 5
// Wait for data to arrive using poll // Wait for data to arrive using poll
// This avoids blocking other threads via the per-display Xlib lock that also // This avoids blocking other threads via the per-display Xlib lock that also
// covers GLX functions // covers GLX functions
@@ -70,11 +73,12 @@ handleEvents(double timeout) {
glfw_ibus_dispatch(&_glfw.x11.xkb.ibus); glfw_ibus_dispatch(&_glfw.x11.xkb.ibus);
glfw_dbus_session_bus_dispatch(); glfw_dbus_session_bus_dispatch();
EVDBG("other dispatch done"); EVDBG("other dispatch done");
if (_glfw.x11.eventLoopData.wakeup_fd_ready) check_for_wakeup_events(&_glfw.x11.eventLoopData);
} }
static bool static bool
waitForX11Event(double timeout) { waitForX11Event(double timeout) {
// returns true iff there is X11 data waiting to be read, does not run watches and timers // returns true if there is X11 data waiting to be read, does not run watches and timers
double end_time = glfwGetTime() + timeout; double end_time = glfwGetTime() + timeout;
while(true) { while(true) {
if (timeout >= 0) { if (timeout >= 0) {
@@ -138,7 +142,7 @@ static int getWindowState(_GLFWwindow* window)
// Returns whether the event is a selection event // Returns whether the event is a selection event
// //
static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer) static Bool isSelectionEvent(Display* display UNUSED, XEvent* event, XPointer pointer UNUSED)
{ {
if (event->xany.window != _glfw.x11.helperWindowHandle) if (event->xany.window != _glfw.x11.helperWindowHandle)
return False; return False;
@@ -150,7 +154,7 @@ static Bool isSelectionEvent(Display* display, XEvent* event, XPointer pointer)
// Returns whether it is a _NET_FRAME_EXTENTS event for the specified window // Returns whether it is a _NET_FRAME_EXTENTS event for the specified window
// //
static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointer) static Bool isFrameExtentsEvent(Display* display UNUSED, XEvent* event, XPointer pointer)
{ {
_GLFWwindow* window = (_GLFWwindow*) pointer; _GLFWwindow* window = (_GLFWwindow*) pointer;
return event->type == PropertyNotify && return event->type == PropertyNotify &&
@@ -161,7 +165,7 @@ static Bool isFrameExtentsEvent(Display* display, XEvent* event, XPointer pointe
// Returns whether it is a property event for the specified selection transfer // Returns whether it is a property event for the specified selection transfer
// //
static Bool isSelPropNewValueNotify(Display* display, XEvent* event, XPointer pointer) static Bool isSelPropNewValueNotify(Display* display UNUSED, XEvent* event, XPointer pointer)
{ {
XEvent* notification = (XEvent*) pointer; XEvent* notification = (XEvent*) pointer;
return event->type == PropertyNotify && return event->type == PropertyNotify &&
@@ -197,10 +201,7 @@ static int translateState(int state)
static void sendEventToWM(_GLFWwindow* window, Atom type, static void sendEventToWM(_GLFWwindow* window, Atom type,
long a, long b, long c, long d, long e) long a, long b, long c, long d, long e)
{ {
XEvent event; XEvent event = { ClientMessage };
memset(&event, 0, sizeof(event));
event.type = ClientMessage;
event.xclient.window = window->x11.handle; event.xclient.window = window->x11.handle;
event.xclient.format = 32; // Data is 32-bit longs event.xclient.format = 32; // Data is 32-bit longs
event.xclient.message_type = type; event.xclient.message_type = type;
@@ -328,8 +329,7 @@ set_fullscreen(_GLFWwindow *window, bool on) {
} }
bool bool
_glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags) { _glfwPlatformToggleFullscreen(_GLFWwindow *window, unsigned int flags UNUSED) {
(void) flags;
bool already_fullscreen = is_window_fullscreen(window); bool already_fullscreen = is_window_fullscreen(window);
set_fullscreen(window, !already_fullscreen); set_fullscreen(window, !already_fullscreen);
return !already_fullscreen; return !already_fullscreen;
@@ -841,11 +841,8 @@ static void handleSelectionRequest(XEvent* event)
{ {
const XSelectionRequestEvent* request = &event->xselectionrequest; const XSelectionRequestEvent* request = &event->xselectionrequest;
XEvent reply; XEvent reply = { SelectionNotify };
memset(&reply, 0, sizeof(reply));
reply.xselection.property = writeTargetToProperty(request); reply.xselection.property = writeTargetToProperty(request);
reply.xselection.type = SelectionNotify;
reply.xselection.display = request->display; reply.xselection.display = request->display;
reply.xselection.requestor = request->requestor; reply.xselection.requestor = request->requestor;
reply.xselection.selection = request->selection; reply.xselection.selection = request->selection;
@@ -857,7 +854,6 @@ static void handleSelectionRequest(XEvent* event)
static const char* getSelectionString(Atom selection) static const char* getSelectionString(Atom selection)
{ {
size_t i;
char** selectionString = NULL; char** selectionString = NULL;
const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING }; const Atom targets[] = { _glfw.x11.UTF8_STRING, XA_STRING };
const size_t targetCount = sizeof(targets) / sizeof(targets[0]); const size_t targetCount = sizeof(targets) / sizeof(targets[0]);
@@ -878,7 +874,7 @@ static const char* getSelectionString(Atom selection)
free(*selectionString); free(*selectionString);
*selectionString = NULL; *selectionString = NULL;
for (i = 0; i < targetCount; i++) for (size_t i = 0; i < targetCount; i++)
{ {
char* data; char* data;
Atom actualType; Atom actualType;
@@ -1075,7 +1071,6 @@ static void onConfigChange(void)
// //
static void processEvent(XEvent *event) static void processEvent(XEvent *event)
{ {
_GLFWwindow* window = NULL;
static bool keymap_dirty = false; static bool keymap_dirty = false;
#define UPDATE_KEYMAP_IF_NEEDED if (keymap_dirty) { keymap_dirty = false; glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL); } #define UPDATE_KEYMAP_IF_NEEDED if (keymap_dirty) { keymap_dirty = false; glfw_xkb_compile_keymap(&_glfw.x11.xkb, NULL); }
@@ -1170,6 +1165,7 @@ static void processEvent(XEvent *event)
return; return;
} }
_GLFWwindow* window = NULL;
if (XFindContext(_glfw.x11.display, if (XFindContext(_glfw.x11.display,
event->xany.window, event->xany.window,
_glfw.x11.context, _glfw.x11.context,
@@ -1487,10 +1483,7 @@ static void processEvent(XEvent *event)
} }
else if (_glfw.x11.xdnd.version >= 2) else if (_glfw.x11.xdnd.version >= 2)
{ {
XEvent reply; XEvent reply = { ClientMessage };
memset(&reply, 0, sizeof(reply));
reply.type = ClientMessage;
reply.xclient.window = _glfw.x11.xdnd.source; reply.xclient.window = _glfw.x11.xdnd.source;
reply.xclient.message_type = _glfw.x11.XdndFinished; reply.xclient.message_type = _glfw.x11.XdndFinished;
reply.xclient.format = 32; reply.xclient.format = 32;
@@ -1523,10 +1516,7 @@ static void processEvent(XEvent *event)
_glfwInputCursorPos(window, xpos, ypos); _glfwInputCursorPos(window, xpos, ypos);
XEvent reply; XEvent reply = { ClientMessage };
memset(&reply, 0, sizeof(reply));
reply.type = ClientMessage;
reply.xclient.window = _glfw.x11.xdnd.source; reply.xclient.window = _glfw.x11.xdnd.source;
reply.xclient.message_type = _glfw.x11.XdndStatus; reply.xclient.message_type = _glfw.x11.XdndStatus;
reply.xclient.format = 32; reply.xclient.format = 32;
@@ -1579,10 +1569,7 @@ static void processEvent(XEvent *event)
if (_glfw.x11.xdnd.version >= 2) if (_glfw.x11.xdnd.version >= 2)
{ {
XEvent reply; XEvent reply = { ClientMessage };
memset(&reply, 0, sizeof(reply));
reply.type = ClientMessage;
reply.xclient.window = _glfw.x11.xdnd.source; reply.xclient.window = _glfw.x11.xdnd.source;
reply.xclient.message_type = _glfw.x11.XdndFinished; reply.xclient.message_type = _glfw.x11.XdndFinished;
reply.xclient.format = 32; reply.xclient.format = 32;
@@ -1601,9 +1588,6 @@ static void processEvent(XEvent *event)
case FocusIn: case FocusIn:
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window);
if (event->xfocus.mode == NotifyGrab || if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab) event->xfocus.mode == NotifyUngrab)
{ {
@@ -1612,15 +1596,15 @@ static void processEvent(XEvent *event)
return; return;
} }
if (window->cursorMode == GLFW_CURSOR_DISABLED)
disableCursor(window);
_glfwInputWindowFocus(window, true); _glfwInputWindowFocus(window, true);
return; return;
} }
case FocusOut: case FocusOut:
{ {
if (window->cursorMode == GLFW_CURSOR_DISABLED)
enableCursor(window);
if (event->xfocus.mode == NotifyGrab || if (event->xfocus.mode == NotifyGrab ||
event->xfocus.mode == NotifyUngrab) event->xfocus.mode == NotifyUngrab)
{ {
@@ -1629,6 +1613,9 @@ static void processEvent(XEvent *event)
return; return;
} }
if (window->cursorMode == GLFW_CURSOR_DISABLED)
enableCursor(window);
if (window->monitor && window->autoIconify) if (window->monitor && window->autoIconify)
_glfwPlatformIconifyWindow(window); _glfwPlatformIconifyWindow(window);
@@ -2025,8 +2012,8 @@ void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height)
} }
void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window, void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
int minwidth, int minheight, int minwidth UNUSED, int minheight UNUSED,
int maxwidth, int maxheight) int maxwidth UNUSED, int maxheight UNUSED)
{ {
int width, height; int width, height;
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
@@ -2034,7 +2021,7 @@ void _glfwPlatformSetWindowSizeLimits(_GLFWwindow* window,
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
} }
void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer, int denom) void _glfwPlatformSetWindowAspectRatio(_GLFWwindow* window, int numer UNUSED, int denom UNUSED)
{ {
int width, height; int width, height;
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
@@ -2107,7 +2094,7 @@ void _glfwPlatformGetWindowFrameSize(_GLFWwindow* window,
XFree(extents); XFree(extents);
} }
void _glfwPlatformGetWindowContentScale(_GLFWwindow* window, void _glfwPlatformGetWindowContentScale(_GLFWwindow* window UNUSED,
float* xscale, float* yscale) float* xscale, float* yscale)
{ {
if (xscale) if (xscale)
@@ -2116,7 +2103,7 @@ void _glfwPlatformGetWindowContentScale(_GLFWwindow* window,
*yscale = _glfw.x11.contentScaleY; *yscale = _glfw.x11.contentScaleY;
} }
double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window) double _glfwPlatformGetDoubleClickInterval(_GLFWwindow* window UNUSED)
{ {
return 0.5; return 0.5;
} }
@@ -2215,7 +2202,7 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
_GLFWmonitor* monitor, _GLFWmonitor* monitor,
int xpos, int ypos, int xpos, int ypos,
int width, int height, int width, int height,
int refreshRate) int refreshRate UNUSED)
{ {
if (window->monitor == monitor) if (window->monitor == monitor)
{ {
@@ -2245,13 +2232,14 @@ void _glfwPlatformSetWindowMonitor(_GLFWwindow* window,
if (window->monitor) if (window->monitor)
{ {
if (!_glfwPlatformWindowVisible(window)) if (!_glfwPlatformWindowVisible(window))
{ {
XMapRaised(_glfw.x11.display, window->x11.handle); XMapRaised(_glfw.x11.display, window->x11.handle);
waitForVisibilityNotify(window); waitForVisibilityNotify(window);
} }
updateWindowMode(window);
acquireMonitor(window); updateWindowMode(window);
acquireMonitor(window);
} }
else else
{ {
@@ -2272,7 +2260,7 @@ int _glfwPlatformWindowFocused(_GLFWwindow* window)
return window->x11.handle == focused; return window->x11.handle == focused;
} }
int _glfwPlatformWindowOccluded(_GLFWwindow* window) int _glfwPlatformWindowOccluded(_GLFWwindow* window UNUSED)
{ {
return false; return false;
} }
@@ -2294,10 +2282,13 @@ int _glfwPlatformWindowMaximized(_GLFWwindow* window)
Atom* states; Atom* states;
unsigned long i; unsigned long i;
bool maximized = false; bool maximized = false;
if (!_glfw.x11.NET_WM_STATE || if (!_glfw.x11.NET_WM_STATE ||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT || !_glfw.x11.NET_WM_STATE_MAXIMIZED_VERT ||
!_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ) !_glfw.x11.NET_WM_STATE_MAXIMIZED_HORZ)
{
return maximized; return maximized;
}
const unsigned long count = const unsigned long count =
_glfwGetWindowPropertyX11(window->x11.handle, _glfwGetWindowPropertyX11(window->x11.handle,
_glfw.x11.NET_WM_STATE, _glfw.x11.NET_WM_STATE,
@@ -2350,7 +2341,7 @@ int _glfwPlatformFramebufferTransparent(_GLFWwindow* window)
return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None; return XGetSelectionOwner(_glfw.x11.display, _glfw.x11.NET_WM_CM_Sx) != None;
} }
void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled) void _glfwPlatformSetWindowResizable(_GLFWwindow* window, bool enabled UNUSED)
{ {
int width, height; int width, height;
_glfwPlatformGetWindowSize(window, &width, &height); _glfwPlatformGetWindowSize(window, &width, &height);
@@ -2485,14 +2476,12 @@ void _glfwPlatformSetWindowOpacity(_GLFWwindow* window, float opacity)
} }
static inline unsigned static inline unsigned
dispatch_x11_queued_events(void) { dispatch_x11_queued_events(int num_events) {
unsigned dispatched = 0; unsigned dispatched = num_events > 0 ? num_events : 0;
while (XQLength(_glfw.x11.display) > 0) while (num_events-- > 0) {
{
XEvent event; XEvent event;
XNextEvent(_glfw.x11.display, &event); XNextEvent(_glfw.x11.display, &event);
processEvent(&event); processEvent(&event);
dispatched += 1;
} }
return dispatched; return dispatched;
} }
@@ -2503,10 +2492,9 @@ _glfwDispatchX11Events(void) {
unsigned dispatched = 0; unsigned dispatched = 0;
#if defined(__linux__) #if defined(__linux__)
_glfwDetectJoystickConnectionLinux(); if (_glfw.hints.init.enableJoysticks) _glfwDetectJoystickConnectionLinux();
#endif #endif
XPending(_glfw.x11.display); dispatched += dispatch_x11_queued_events(XEventsQueued(_glfw.x11.display, QueuedAfterFlush));
dispatched += dispatch_x11_queued_events();
window = _glfw.x11.disabledCursorWindow; window = _glfw.x11.disabledCursorWindow;
if (window) if (window)
@@ -2524,8 +2512,10 @@ _glfwDispatchX11Events(void) {
} }
XFlush(_glfw.x11.display); XFlush(_glfw.x11.display);
// XFlush can cause events to be queued // XFlush can cause events to be queued, we don't use QueuedAfterFlush here
dispatched += dispatch_x11_queued_events(); // 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));
return dispatched; return dispatched;
} }
@@ -2549,7 +2539,7 @@ void _glfwPlatformWaitEventsTimeout(double timeout)
void _glfwPlatformPostEmptyEvent(void) void _glfwPlatformPostEmptyEvent(void)
{ {
while (write(_glfw.x11.eventLoopData.wakeupFds[1], "w", 1) < 0 && errno == EINTR); wakeupEventLoop(&_glfw.x11.eventLoopData);
} }
void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos) void _glfwPlatformGetCursorPos(_GLFWwindow* window, double* xpos, double* ypos)
@@ -2608,7 +2598,7 @@ int _glfwPlatformGetKeyScancode(int key)
int _glfwPlatformCreateCursor(_GLFWcursor* cursor, int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
const GLFWimage* image, const GLFWimage* image,
int xhot, int yhot, int count) int xhot, int yhot, int count UNUSED)
{ {
cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot); cursor->x11.handle = _glfwCreateCursorX11(image, xhot, yhot);
if (!cursor->x11.handle) if (!cursor->x11.handle)
@@ -2654,7 +2644,7 @@ void _glfwPlatformDestroyCursor(_GLFWcursor* cursor)
XFreeCursor(_glfw.x11.display, cursor->x11.handle); XFreeCursor(_glfw.x11.display, cursor->x11.handle);
} }
void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor) void _glfwPlatformSetCursor(_GLFWwindow* window, _GLFWcursor* cursor UNUSED)
{ {
if (window->cursorMode == GLFW_CURSOR_NORMAL) if (window->cursorMode == GLFW_CURSOR_NORMAL)
{ {

132
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> // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
// //
@@ -29,6 +29,7 @@
#include <stdlib.h> #include <stdlib.h>
#include "internal.h" #include "internal.h"
#include "xkb_glfw.h" #include "xkb_glfw.h"
START_ALLOW_CASE_RANGE
#define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__); #define debug(...) if (_glfw.hints.init.debugKeyboard) printf(__VA_ARGS__);
@@ -36,19 +37,130 @@
#define map_key(key) \ #define map_key(key) \
switch(key) { \ switch(key) { \
S(space, SPACE); \ S(space, SPACE); \
S(exclam, EXCLAM); \
S(quotedbl, DOUBLE_QUOTE); \
S(numbersign, NUMBER_SIGN); \
S(dollar, DOLLAR); \
S(ampersand, AMPERSAND); \
S(apostrophe, APOSTROPHE); \ S(apostrophe, APOSTROPHE); \
S(parenleft, PARENTHESIS_LEFT); \
S(parenright, PARENTHESIS_RIGHT); \
S(plus, PLUS); \
S(comma, COMMA); \ S(comma, COMMA); \
S(minus, MINUS); \ S(minus, MINUS); \
S(period, PERIOD); \ S(period, PERIOD); \
S(slash, SLASH); \ S(slash, SLASH); \
R(0, 9, 0, 9); \
S(colon, COLON); \
S(semicolon, SEMICOLON); \ S(semicolon, SEMICOLON); \
S(less, LESS); \
S(equal, EQUAL); \ S(equal, EQUAL); \
S(greater, GREATER); \
S(at, AT); \
D(A, Z, A, Z); \
S(bracketleft, LEFT_BRACKET); \ S(bracketleft, LEFT_BRACKET); \
S(backslash, BACKSLASH); \ S(backslash, BACKSLASH); \
S(bracketright, RIGHT_BRACKET); \ S(bracketright, RIGHT_BRACKET); \
S(plus, PLUS); \
S(underscore, UNDERSCORE); \ S(underscore, UNDERSCORE); \
S(grave, GRAVE_ACCENT); \ 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(Escape, ESCAPE); \
S(Return, ENTER); \ S(Return, ENTER); \
S(Tab, TAB); \ S(Tab, TAB); \
@@ -90,9 +202,6 @@
S(Alt_R, RIGHT_ALT); \ S(Alt_R, RIGHT_ALT); \
S(Super_R, RIGHT_SUPER); \ S(Super_R, RIGHT_SUPER); \
S(Menu, MENU); \ S(Menu, MENU); \
R(0, 9, 0, 9); \
R(a, z, A, Z); \
D(A, Z, A, Z); \
R(F1, F25, F1, F25); \ R(F1, F25, F1, F25); \
R(KP_0, KP_9, KP_0, KP_9); \ R(KP_0, KP_9, KP_0, KP_9); \
@@ -101,7 +210,7 @@ glfw_key_for_sym(xkb_keysym_t key) {
#define S(f, t) case XKB_KEY_##f: return GLFW_KEY_##t #define S(f, t) case XKB_KEY_##f: return GLFW_KEY_##t
#define F(f, t) S(f, t) #define F(f, t) S(f, t)
#define R(s, e, gs, ...) case XKB_KEY_##s ... XKB_KEY_##e: return GLFW_KEY_##gs + key - XKB_KEY_##s #define R(s, e, gs, ...) case XKB_KEY_##s ... XKB_KEY_##e: return GLFW_KEY_##gs + key - XKB_KEY_##s
#define D(s, e, gs, ...) R(s, e, gs) #define D(s, e, gs, ...) R(s, e, gs, __VA_ARGS__)
map_key(key) map_key(key)
S(KP_Up, UP); S(KP_Up, UP);
S(KP_Down, DOWN); S(KP_Down, DOWN);
@@ -115,7 +224,7 @@ glfw_key_for_sym(xkb_keysym_t key) {
#undef D #undef D
#undef R #undef R
#undef S #undef S
}; }
xkb_keysym_t xkb_keysym_t
glfw_xkb_sym_for_key(int key) { glfw_xkb_sym_for_key(int key) {
@@ -133,6 +242,7 @@ glfw_xkb_sym_for_key(int key) {
#undef R #undef R
#undef S #undef S
} }
END_ALLOW_CASE_RANGE
#ifdef _GLFW_X11 #ifdef _GLFW_X11
@@ -167,7 +277,7 @@ glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
if (conn) keymap = xkb_x11_keymap_new_from_device(xkb->context, conn, xkb->keyboard_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); \ if (conn) keymap = xkb_x11_keymap_new_from_device(xkb->context, conn, xkb->keyboard_device_id, XKB_KEYMAP_COMPILE_NO_FLAGS); \
} }
#define xkb_glfw_load_state(keymap, state, ...) {\ #define xkb_glfw_load_state(keymap, state) {\
xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display); \ xcb_connection_t* conn = XGetXCBConnection(_glfw.x11.display); \
if (conn) state = xkb_x11_state_new_from_device(keymap, conn, xkb->keyboard_device_id); \ if (conn) state = xkb_x11_state_new_from_device(keymap, conn, xkb->keyboard_device_id); \
} }
@@ -175,7 +285,7 @@ glfw_xkb_update_x11_keyboard_id(_GLFWXKBData *xkb) {
#else #else
#define xkb_glfw_load_keymap(keymap, map_str) keymap = xkb_keymap_new_from_string(xkb->context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); #define xkb_glfw_load_keymap(keymap, map_str) keymap = xkb_keymap_new_from_string(xkb->context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0);
#define xkb_glfw_load_state(keymap, state, ...) state = xkb_state_new(keymap); #define xkb_glfw_load_state(keymap, state) state = xkb_state_new(keymap);
#endif #endif
@@ -335,7 +445,7 @@ glfw_xkb_should_repeat(_GLFWXKBData *xkb, xkb_keycode_t scancode) {
} }
static KeyEvent key_event = {}; static KeyEvent key_event = {0};
static inline xkb_keysym_t 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) {
@@ -432,7 +542,7 @@ glfw_xkb_key_from_ime(KeyEvent *ev, bool handled_by_ime, bool failed) {
} }
static xkb_keycode_t last_handled_press_keycode = 0; static xkb_keycode_t last_handled_press_keycode = 0;
// We filter out release events that correspond to the last press event // 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 // 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. // you'd need to implement a ring buffer to store pending key presses.
xkb_keycode_t prev_handled_press = last_handled_press_keycode; xkb_keycode_t prev_handled_press = last_handled_press_keycode;

6
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> // Copyright (c) 2018 Kovid Goyal <kovid@kovidgoyal.net>
// //
@@ -67,8 +67,8 @@ typedef struct {
#ifdef _GLFW_X11 #ifdef _GLFW_X11
int32_t keyboard_device_id; int32_t keyboard_device_id;
bool available; bool available;
bool detectable; bool detectable;
int majorOpcode; int majorOpcode;
int eventBase; int eventBase;
int errorBase; int errorBase;

View File

@@ -25,9 +25,9 @@ static inline ssize_t ms_write(int fd, const void* buf, size_t count) { return _
static inline bool static inline bool
ensure_space(GlobalData *global, size_t sz) { ensure_space(GlobalData *global, size_t sz) {
if (global->output_sz < sz + global->output_pos) { if (global->output_sz < sz + global->output_pos || !global->output) {
size_t before = global->output_sz; size_t before = global->output_sz;
global->output_sz += MAX(sz, (64 * 1024)); global->output_sz += MAX(sz, (64u * 1024u));
global->output = realloc(global->output, sizeof(text_t) * global->output_sz); global->output = realloc(global->output, sizeof(text_t) * global->output_sz);
if (!global->output) { if (!global->output) {
global->output_sz = before; global->output_sz = before;

View File

@@ -20,7 +20,7 @@ from ..tui.loop import Loop
from ..tui.operations import faint, styled from ..tui.operations import faint, styled
URL_PREFIXES = 'http https file ftp'.split() URL_PREFIXES = 'http https file ftp'.split()
HINT_ALPHABET = string.digits + string.ascii_lowercase DEFAULT_HINT_ALPHABET = string.digits + string.ascii_lowercase
screen_size = screen_size_function() screen_size = screen_size_function()
@@ -34,21 +34,26 @@ class Mark:
@lru_cache(maxsize=2048) @lru_cache(maxsize=2048)
def encode_hint(num): def encode_hint(num, alphabet):
res = '' res = ''
d = len(HINT_ALPHABET) d = len(alphabet)
while not res or num > 0: while not res or num > 0:
num, i = divmod(num, d) num, i = divmod(num, d)
res = HINT_ALPHABET[i] + res res = alphabet[i] + res
return res return res
def decode_hint(x): def decode_hint(x, alphabet=DEFAULT_HINT_ALPHABET):
return int(x, 36) 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): def highlight_mark(m, text, current_input, alphabet):
hint = encode_hint(m.index) hint = encode_hint(m.index, alphabet)
if current_input and not hint.startswith(current_input): if current_input and not hint.startswith(current_input):
return faint(text) return faint(text)
hint = hint[len(current_input):] or ' ' hint = hint[len(current_input):] or ' '
@@ -63,11 +68,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): for mark in reversed(all_marks):
if mark.index in ignore_mark_indices: if mark.index in ignore_mark_indices:
continue 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[:mark.start] + mtext + text[mark.end:]
text = text.replace('\0', '') text = text.replace('\0', '')
@@ -79,6 +84,7 @@ class Hints(Handler):
def __init__(self, text, all_marks, index_map, args): def __init__(self, text, all_marks, index_map, args):
self.text, self.index_map = text, index_map self.text, self.index_map = text, index_map
self.alphabet = args.alphabet or DEFAULT_HINT_ALPHABET
self.all_marks = all_marks self.all_marks = all_marks
self.ignore_mark_indices = set() self.ignore_mark_indices = set()
self.args = args self.args = args
@@ -111,13 +117,13 @@ class Hints(Handler):
def on_text(self, text, in_bracketed_paste): def on_text(self, text, in_bracketed_paste):
changed = False changed = False
for c in text: for c in text:
if c in HINT_ALPHABET: if c in self.alphabet:
self.current_input += c self.current_input += c
changed = True changed = True
if changed: if changed:
matches = [ matches = [
m for idx, m in self.index_map.items() 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: if len(matches) == 1:
self.chosen.append(matches[0].text + self.match_suffix) self.chosen.append(matches[0].text + self.match_suffix)
@@ -137,7 +143,7 @@ class Hints(Handler):
self.draw_screen() self.draw_screen()
elif key_event is enter_key and self.current_input: elif key_event is enter_key and self.current_input:
try: try:
idx = decode_hint(self.current_input) idx = decode_hint(self.current_input, self.alphabet)
self.chosen.append(self.index_map[idx].text + self.match_suffix) self.chosen.append(self.index_map[idx].text + self.match_suffix)
self.ignore_mark_indices.add(idx) self.ignore_mark_indices.add(idx)
except Exception: except Exception:
@@ -164,7 +170,7 @@ class Hints(Handler):
def draw_screen(self): def draw_screen(self):
if self.current_text is None: 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.cmd.clear_screen()
self.write(self.current_text) self.write(self.current_text)
@@ -246,7 +252,7 @@ def run_loop(args, text, all_marks, index_map):
handler = Hints(text, all_marks, index_map, args) handler = Hints(text, all_marks, index_map, args)
loop.loop(handler) loop.loop(handler)
if handler.chosen and loop.return_code == 0: if handler.chosen and loop.return_code == 0:
return {'match': handler.chosen, 'program': args.program, return {'match': handler.chosen, 'programs': args.program,
'multiple_joiner': args.multiple_joiner, 'multiple_joiner': args.multiple_joiner,
'type': args.type} 'type': args.type}
raise SystemExit(loop.return_code) raise SystemExit(loop.return_code)
@@ -333,10 +339,12 @@ def run(args, text):
# CLI {{{ # CLI {{{
OPTIONS = r''' OPTIONS = r'''
--program --program
default=default type=list
What program to use to open matched text. Defaults to the default open program What program to use to open matched text. Defaults to the default open program
for the operating system. Use a value of :file:`-` to paste the match into the for the operating system. Use a value of :file:`-` to paste the match into the
terminal window instead. A value of :file:`@` will copy the match to the clipboard. terminal window instead. A value of :file:`@` will copy the match to the clipboard.
A value of :file:`default` will run the default open program. Can be specified
multiple times to run multiple programs.
--type --type
@@ -348,9 +356,11 @@ The type of text to search for.
--regex --regex
default=(?m)^\s*(.+)\s*$ default=(?m)^\s*(.+)\s*$
The regular expression to use when :option:`kitty +kitten hints --type`=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 The regular expression is in python syntax. If you specify a group in
will be matched. This allow you to match text ignoring a prefix/suffix, as the regular expression only the group will be matched. This allow you to match
needed. The default expression matches lines. 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.
--url-prefixes --url-prefixes
@@ -360,7 +370,7 @@ Comma separated list of recognized URL prefixes.
--word-characters --word-characters
Characters to consider as part of a word. In addition, all characters marked as 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. Defaults to the select_by_word_characters setting from kitty.conf.
@@ -399,6 +409,15 @@ default=1
type=int type=int
The offset (from zero) at which to start hint numbering. Note that only numbers The offset (from zero) at which to start hint numbering. Note that only numbers
greater than or equal to zero are respected. greater than or equal to zero are respected.
--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.
'''.format(','.join(sorted(URL_PREFIXES))).format '''.format(','.join(sorted(URL_PREFIXES))).format
help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.' help_text = 'Select text from the screen using the keyboard. Defaults to searching for URLs.'
usage = '' usage = ''
@@ -428,12 +447,11 @@ def main(args):
if items: if items:
print('Extra command line arguments present: {}'.format(' '.join(items)), file=sys.stderr) print('Extra command line arguments present: {}'.format(' '.join(items)), file=sys.stderr)
input(_('Press Enter to quit')) input(_('Press Enter to quit'))
return
return run(args, text) return run(args, text)
def handle_result(args, data, target_window_id, boss): def handle_result(args, data, target_window_id, boss):
program = data['program'] programs = data['programs'] or ('default',)
matches = tuple(filter(None, data['match'])) matches = tuple(filter(None, data['match']))
joiner = data['multiple_joiner'] joiner = data['multiple_joiner']
try: try:
@@ -442,6 +460,7 @@ def handle_result(args, data, target_window_id, boss):
is_int = None is_int = None
text_type = data['type'] text_type = data['type']
@lru_cache()
def joined_text(): def joined_text():
if is_int is not None: if is_int is not None:
try: try:
@@ -457,20 +476,21 @@ def handle_result(args, data, target_window_id, boss):
q = {'newline': '\n\r', 'space': ' '}.get(joiner, '') q = {'newline': '\n\r', 'space': ' '}.get(joiner, '')
return q.join(matches) return q.join(matches)
if program == '-': for program in programs:
w = boss.window_id_map.get(target_window_id) if program == '-':
if w is not None: w = boss.window_id_map.get(target_window_id)
w.paste(joined_text()) if w is not None:
elif program == '@': w.paste(joined_text())
set_clipboard_string(joined_text()) elif program == '@':
else: set_clipboard_string(joined_text())
cwd = None else:
w = boss.window_id_map.get(target_window_id) cwd = None
if w is not None: w = boss.window_id_map.get(target_window_id)
cwd = w.cwd_of_child if w is not None:
program = None if program == 'default' else program cwd = w.cwd_of_child
for m in matches: program = None if program == 'default' else program
boss.open_url(m, program, cwd=cwd) for m in matches:
boss.open_url(m, program, cwd=cwd)
handle_result.type_of_input = 'screen' handle_result.type_of_input = 'screen'

View File

@@ -194,11 +194,13 @@ def process(path, args, is_tempfile):
available_height = args.place.height * (ss.height / ss.rows) if args.place else 10 * m.height 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 = m.width > available_width or m.height > available_height
needs_scaling = needs_scaling or args.scale_up needs_scaling = needs_scaling or args.scale_up
file_removed = False
if m.fmt == 'png' and not needs_scaling: if m.fmt == 'png' and not needs_scaling:
outfile = path outfile = path
transmit_mode = 't' if is_tempfile else 'f' transmit_mode = 't' if is_tempfile else 'f'
fmt = 100 fmt = 100
width, height = m.width, m.height width, height = m.width, m.height
file_removed = transmit_mode == 't'
else: else:
fmt = 24 if m.mode == 'rgb' else 32 fmt = 24 if m.mode == 'rgb' else 32
transmit_mode = 't' transmit_mode = 't'
@@ -206,6 +208,7 @@ def process(path, args, is_tempfile):
show(outfile, width, height, fmt, transmit_mode, align=args.align, place=args.place) show(outfile, width, height, fmt, transmit_mode, align=args.align, place=args.place)
if not args.place: if not args.place:
print() # ensure cursor is on a new line print() # ensure cursor is on a new line
return file_removed
def scan(d): def scan(d):
@@ -272,6 +275,7 @@ usage = 'image-file-or-url-or-directory ...'
def process_single_item(item, args, url_pat=None, maybe_dir=True): def process_single_item(item, args, url_pat=None, maybe_dir=True):
is_tempfile = False is_tempfile = False
file_removed = False
try: try:
if isinstance(item, bytes): if isinstance(item, bytes):
tf = NamedTemporaryFile(prefix='stdin-image-data-', delete=False) tf = NamedTemporaryFile(prefix='stdin-image-data-', delete=False)
@@ -287,7 +291,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)) raise SystemExit('Failed to download image at URL: {} with error: {}'.format(item, e))
item = tf.name item = tf.name
is_tempfile = True is_tempfile = True
process(item, args, is_tempfile) file_removed = process(item, args, is_tempfile)
elif item.lower().startswith('file://'): elif item.lower().startswith('file://'):
from urllib.parse import urlparse from urllib.parse import urlparse
from urllib.request import url2pathname from urllib.request import url2pathname
@@ -297,15 +301,15 @@ def process_single_item(item, args, url_pat=None, maybe_dir=True):
else: else:
item = item.path item = item.path
item = url2pathname(item) item = url2pathname(item)
process(item, args, is_tempfile) file_removed = process(item, args, is_tempfile)
else: else:
if maybe_dir and os.path.isdir(item): if maybe_dir and os.path.isdir(item):
for (x, mt) in scan(item): for (x, mt) in scan(item):
process_single_item(x, args, url_pat=None, maybe_dir=False) process_single_item(x, args, url_pat=None, maybe_dir=False)
else: else:
process(item, args, is_tempfile) file_removed = process(item, args, is_tempfile)
finally: finally:
if is_tempfile: if is_tempfile and not file_removed:
os.remove(item) os.remove(item)

View File

@@ -6,6 +6,7 @@
import importlib import importlib
import os import os
import sys import sys
from contextlib import suppress
from functools import partial from functools import partial
aliases = {'url_hints': 'hints'} aliases = {'url_hints': 'hints'}
@@ -15,13 +16,18 @@ def resolved_kitten(k):
return aliases.get(k, k).replace('-', '_') return aliases.get(k, k).replace('-', '_')
def path_to_custom_kitten(config_dir, kitten):
path = os.path.expanduser(kitten)
if not os.path.isabs(path):
path = os.path.join(config_dir, path)
path = os.path.abspath(path)
return path
def import_kitten_main_module(config_dir, kitten): def import_kitten_main_module(config_dir, kitten):
if kitten.endswith('.py'): if kitten.endswith('.py'):
path_modified = False path_modified = False
path = os.path.expanduser(kitten) path = path_to_custom_kitten(config_dir, kitten)
if not os.path.isabs(path):
path = os.path.join(config_dir, path)
path = os.path.abspath(path)
if os.path.dirname(path): if os.path.dirname(path):
sys.path.insert(0, os.path.dirname(path)) sys.path.insert(0, os.path.dirname(path))
path_modified = True path_modified = True
@@ -90,12 +96,24 @@ def deserialize(output):
def run_kitten(kitten, run_name='__main__'): def run_kitten(kitten, run_name='__main__'):
import runpy import runpy
original_kitten_name = kitten
kitten = resolved_kitten(kitten) kitten = resolved_kitten(kitten)
set_debug(kitten) set_debug(kitten)
try: with suppress(ImportError):
runpy.run_module('kittens.{}.main'.format(kitten), run_name=run_name) runpy.run_module('kittens.{}.main'.format(kitten), run_name=run_name)
except ImportError: return
raise SystemExit('No kitten named {}'.format(kitten)) # Look for a custom kitten
if not kitten.endswith('.py'):
kitten += '.py'
from kitty.constants import config_dir
path = path_to_custom_kitten(config_dir, kitten)
if not os.path.exists(path):
print('Available builtin kittens:', file=sys.stderr)
for kitten in all_kitten_names():
print(kitten, file=sys.stderr)
raise SystemExit('No kitten named {}'.format(original_kitten_name))
m = runpy.run_path(path, init_globals={'sys': sys, 'os': os}, run_name='__run_kitten__')
m['main'](sys.argv)
def all_kitten_names(): def all_kitten_names():

View File

@@ -4,6 +4,7 @@
import os import os
import re import re
import shlex
import subprocess import subprocess
import sys import sys
@@ -93,6 +94,18 @@ def parse_ssh_args(args):
return ssh_args, server_args, passthrough return ssh_args, server_args, passthrough
def quote(x):
# 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
try:
shlex.split(x)
except ValueError:
x = shlex.quote(x)
return x
def main(args): def main(args):
ssh_args, server_args, passthrough = parse_ssh_args(args[1:]) ssh_args, server_args, passthrough = parse_ssh_args(args[1:])
if passthrough: if passthrough:
@@ -101,7 +114,7 @@ def main(args):
terminfo = subprocess.check_output(['infocmp']).decode('utf-8') terminfo = subprocess.check_output(['infocmp']).decode('utf-8')
sh_script = SHELL_SCRIPT.replace('TERMINFO', terminfo, 1) sh_script = SHELL_SCRIPT.replace('TERMINFO', terminfo, 1)
if len(server_args) > 1: if len(server_args) > 1:
command_to_execute = ["'{}'".format(c.replace("'", """'"'"'""")) for c in server_args[1:]] command_to_execute = [quote(c) for c in server_args[1:]]
command_to_execute = 'exec ' + ' '.join(command_to_execute) command_to_execute = 'exec ' + ' '.join(command_to_execute)
else: else:
command_to_execute = '' command_to_execute = ''

View File

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

View File

@@ -240,11 +240,10 @@ class Table:
def is_index(w): def is_index(w):
try: with suppress(Exception):
int(w.lstrip(INDEX_CHAR), 16) int(w.lstrip(INDEX_CHAR), 16)
return True return True
except Exception: return False
return False
class UnicodeInput(Handler): class UnicodeInput(Handler):
@@ -295,9 +294,10 @@ class UnicodeInput(Handler):
self.current_char = None self.current_char = None
if self.mode is HEX: if self.mode is HEX:
with suppress(Exception): with suppress(Exception):
if self.line_edit.current_input.startswith(INDEX_CHAR) and len(self.line_edit.current_input) > 1: if self.line_edit.current_input.startswith(INDEX_CHAR):
self.current_char = chr(self.table.codepoint_at_hint(self.line_edit.current_input[1:])) if len(self.line_edit.current_input) > 1:
else: self.current_char = chr(self.table.codepoint_at_hint(self.line_edit.current_input[1:]))
elif self.line_edit.current_input:
code = int(self.line_edit.current_input, 16) code = int(self.line_edit.current_input, 16)
self.current_char = chr(code) self.current_char = chr(code)
elif self.mode is NAME: elif self.mode is NAME:
@@ -392,19 +392,20 @@ class UnicodeInput(Handler):
try: try:
val = int(self.line_edit.current_input, 16) val = int(self.line_edit.current_input, 16)
except Exception: except Exception:
return pass
if key_event.key is TAB: else:
self.line_edit.current_input = hex(val + 0x10)[2:] if key_event.key is TAB:
self.refresh() self.line_edit.current_input = hex(val + 0x10)[2:]
return self.refresh()
if key_event.key is UP: return
self.line_edit.current_input = hex(val + 1)[2:] if key_event.key is UP:
self.refresh() self.line_edit.current_input = hex(val + 1)[2:]
return self.refresh()
if key_event.key is DOWN: return
self.line_edit.current_input = hex(val - 1)[2:] if key_event.key is DOWN:
self.refresh() self.line_edit.current_input = hex(val - 1)[2:]
return self.refresh()
return
if self.mode is NAME and key_event.type is not RELEASE and not key_event.mods: if self.mode is NAME and key_event.type is not RELEASE and not key_event.mods:
if key_event.key is TAB: if key_event.key is TAB:
if key_event.mods == SHIFT: if key_event.mods == SHIFT:

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -68,7 +68,7 @@ class Borders:
bw, pw = self.border_width, self.padding_width bw, pw = self.border_width, self.padding_width
if bw + pw <= 0: if bw + pw <= 0:
return return
draw_borders = bw > 0 and draw_window_borders and len(windows) > 1 draw_borders = bw > 0 and draw_window_borders
if draw_borders: if draw_borders:
border_data = current_layout.resolve_borders(windows, active_window) border_data = current_layout.resolve_borders(windows, active_window)

View File

@@ -6,12 +6,12 @@ import atexit
import json import json
import os import os
import re import re
from contextlib import suppress
from functools import partial from functools import partial
from gettext import gettext as _ from gettext import gettext as _
from weakref import WeakValueDictionary from weakref import WeakValueDictionary
from contextlib import suppress
from .child import cached_process_data from .child import cached_process_data, cwd_of_process
from .cli import create_opts, parse_args from .cli import create_opts, parse_args
from .conf.utils import to_cmdline from .conf.utils import to_cmdline
from .config import initial_window_size_func, prepare_config_file_for_editing from .config import initial_window_size_func, prepare_config_file_for_editing
@@ -25,8 +25,8 @@ from .fast_data_types import (
change_os_window_state, create_os_window, current_os_window, change_os_window_state, create_os_window, current_os_window,
destroy_global_data, get_clipboard_string, global_font_size, destroy_global_data, get_clipboard_string, global_font_size,
mark_os_window_for_close, os_window_font_size, patch_global_colors, mark_os_window_for_close, os_window_font_size, patch_global_colors,
set_clipboard_string, set_in_sequence_mode, toggle_fullscreen, safe_pipe, set_clipboard_string, set_in_sequence_mode, thread_write,
toggle_maximized toggle_fullscreen, toggle_maximized
) )
from .keys import get_shortcut, shortcut_matches from .keys import get_shortcut, shortcut_matches
from .layout import set_layout_options from .layout import set_layout_options
@@ -619,12 +619,12 @@ class Boss:
if tm is not None: if tm is not None:
tm.update_tab_bar_data() 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) tm = self.os_window_map.get(os_window_id)
if tm is not None: if tm is not None:
w = tm.active_window w = tm.active_window
if w is not None: 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): def on_os_window_closed(self, os_window_id, viewport_width, viewport_height):
self.cached_values['window-size'] = viewport_width, viewport_height self.cached_values['window-size'] = viewport_width, viewport_height
@@ -716,7 +716,9 @@ class Boss:
}, },
cwd=w.cwd_of_child, cwd=w.cwd_of_child,
overlay_for=w.id overlay_for=w.id
)) ),
copy_colors_from=w
)
overlay_window.action_on_close = partial(self.on_kitten_finish, w.id, end_kitten) overlay_window.action_on_close = partial(self.on_kitten_finish, w.id, end_kitten)
return overlay_window return overlay_window
@@ -846,7 +848,8 @@ class Boss:
def set_active_tab(self, tab): def set_active_tab(self, tab):
tm = self.active_tab_manager tm = self.active_tab_manager
if tm is not None: if tm is not None:
tm.set_active_tab(tab) return tm.set_active_tab(tab)
return False
def next_tab(self): def next_tab(self):
tm = self.active_tab_manager tm = self.active_tab_manager
@@ -918,11 +921,22 @@ class Boss:
else: else:
import subprocess import subprocess
env, stdin = self.process_stdin_source(stdin=source, window=window) 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: if stdin:
p = subprocess.Popen(cmd, env=env, stdin=subprocess.PIPE) r, w = safe_pipe(False)
p.communicate(stdin) 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: else:
subprocess.Popen(cmd) subprocess.Popen(cmd, env=env, cwd=cwd)
def args_to_special_window(self, args, cwd_from=None): def args_to_special_window(self, args, cwd_from=None):
args = list(args) args = list(args)
@@ -977,10 +991,14 @@ class Boss:
def _new_window(self, args, cwd_from=None): def _new_window(self, args, cwd_from=None):
tab = self.active_tab tab = self.active_tab
if tab is not None: if tab is not None:
location = None
if args and args[0].startswith('!'):
location = args[0][1:].lower()
args = args[1:]
if args: if args:
return tab.new_special_window(self.args_to_special_window(args, cwd_from=cwd_from)) return tab.new_special_window(self.args_to_special_window(args, cwd_from=cwd_from), location=location)
else: else:
return tab.new_window(cwd_from=cwd_from) return tab.new_window(cwd_from=cwd_from, location=location)
def new_window(self, *args): def new_window(self, *args):
self._new_window(args) self._new_window(args)

View File

@@ -51,10 +51,48 @@ vec4 alpha_blend_premul(vec3 over, float over_alpha, vec3 under, float under_alp
float alpha = mix(under_alpha, 1.0f, over_alpha); float alpha = mix(under_alpha, 1.0f, over_alpha);
return vec4(premul_blend(over, over_alpha, under), alpha); return vec4(premul_blend(over, over_alpha, under), alpha);
} }
vec4 blend_onto_opaque_premul(vec3 over, float over_alpha, vec3 under) {
// same as alpha_blend_premul with under_alpha = 1 outputs a blended color
// with alpha 1 which is effectively pre-multiplied since alpha is 1
return vec4(premul_blend(over, over_alpha, under), 1.0);
}
// }}} // }}}
/*
* Explanation of rendering:
* There are a couple of cases, in order of increasing complexity:
* 1) Simple -- this path is used when there are either no images, or all images are
* drawn on top of text and the background is opaque. In this case, there is a single pass,
* of this shader with cell foreground and background colors blended directly.
* Expected output is a color premultiplied by alpha, with an alpha specified as well.
*
* 2) Interleaved -- this path is used if background is not opaque and there are images or
* if the background is opaque but there are images under text. Rendering happens in
* multiple passes drawing the background and foreground separately and blending.
*
* 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
*
* 2b) Transparent bg with images
* First everything is rendered into a framebuffer, and then the framebauffer is blended onto
* the screen. The framebuffer is needed because it allows access to the background color pixels
* to blend with the image pixels. The steps are basically the same as for 2a.
*
* In this shader exactly *one* of SIMPLE, SPECIAL, FOREGROUND or BACKGROUND will be defined, corresponding
* to the appropriate rendering pass from above.
*/
#ifdef NEEDS_FOREGROUND #ifdef NEEDS_FOREGROUND
vec4 calculate_foreground() { vec4 calculate_foreground() {
// returns the effective foreground color in pre-multiplied form
vec4 text_fg = texture(sprites, sprite_pos); vec4 text_fg = texture(sprites, sprite_pos);
vec3 fg = mix(foreground, text_fg.rgb, colored_sprite); vec3 fg = mix(foreground, text_fg.rgb, colored_sprite);
float text_alpha = text_fg.a; float text_alpha = text_fg.a;
@@ -70,15 +108,12 @@ vec4 calculate_foreground() {
#endif #endif
void main() { void main() {
#ifdef BACKGROUND #ifdef SIMPLE
vec4 fg = calculate_foreground();
#ifdef TRANSPARENT #ifdef TRANSPARENT
// bg_alpha is doubled to match rendering in the SIMPLE case final_color = alpha_blend_premul(fg.rgb, fg.a, background.rgb * bg_alpha, bg_alpha);
// and also rendering of the margin/padding, see https://github.com/kovidgoyal/kitty/pull/1291
// to test use background_opacity, window_margin_width and icat to display
// an image.
final_color = vec4(background.rgb * bg_alpha * bg_alpha, bg_alpha);
#else #else
final_color = vec4(background.rgb, 1.0f); final_color = blend_onto_opaque_premul(fg.rgb, fg.a, background.rgb);
#endif #endif
#endif #endif
@@ -90,29 +125,22 @@ void main() {
#endif #endif
#endif #endif
#if defined(FOREGROUND) || defined(SIMPLE) #ifdef BACKGROUND
// FOREGROUND or SIMPLE #ifdef TRANSPARENT
vec4 fg = calculate_foreground(); // pre-multiplied foreground final_color = vec4(background.rgb * bg_alpha, bg_alpha);
#else
final_color = vec4(background.rgb, 1.0f);
#endif
#endif
#ifdef FOREGROUND #ifdef FOREGROUND
// FOREGROUND vec4 fg = calculate_foreground(); // pre-multiplied foreground
#ifdef TRANSPARENT #ifdef TRANSPARENT
final_color = fg; final_color = fg;
#else #else
final_color = vec4(fg.rgb / fg.a, fg.a); final_color = vec4(fg.rgb / fg.a, fg.a);
#endif #endif
#else
// SIMPLE
#ifdef TRANSPARENT
final_color = alpha_blend_premul(fg.rgb, fg.a, background * bg_alpha, bg_alpha);
final_color = vec4(final_color.rgb, final_color.a);
#else
// since background alpha is 1.0, it is effectively pre-multiplied
final_color = vec4(premul_blend(fg.rgb, fg.a, background), 1.0f);
final_color = vec4(final_color.rgb, final_color.a);
#endif
#endif #endif
#endif
} }

View File

@@ -114,7 +114,7 @@ vec3 choose_color(float q, vec3 a, vec3 b) {
return mix(b, a, q); 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 float delta = abs(a - b); // delta can be 0, 1 or larger
return step(delta, 0.5); // 0 if 0.5 < delta else 1 return step(delta, 0.5); // 0 if 0.5 < delta else 1
} }
@@ -172,13 +172,15 @@ void main() {
foreground = color_to_vec(resolved_fg); foreground = color_to_vec(resolved_fg);
float has_dim = float((text_attrs >> DIM_SHIFT) & ONE); float has_dim = float((text_attrs >> DIM_SHIFT) & ONE);
effective_text_alpha = inactive_text_alpha * mix(1.0, dim_opacity, has_dim); effective_text_alpha = inactive_text_alpha * mix(1.0, dim_opacity, has_dim);
#ifdef USE_SELECTION_FG
// Selection
foreground = choose_color(float(is_selected & ONE), color_to_vec(highlight_fg), foreground);
#endif
// Underline and strike through (rendered via sprites)
float in_url = float((is_selected & TWO) >> 1); 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)); decoration_fg = choose_color(in_url, color_to_vec(url_color), to_color(colors[2], resolved_fg));
#ifdef USE_SELECTION_FG
// Selection
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)
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)); 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); strike_pos = to_sprite_pos(pos, ((text_attrs >> STRIKE_SHIFT) & ONE) * FOUR, ZERO, ZERO);

View File

@@ -5,6 +5,7 @@
* Distributed under terms of the GPL3 license. * Distributed under terms of the GPL3 license.
*/ */
#include "loop-utils.h"
#include "state.h" #include "state.h"
#include "threading.h" #include "threading.h"
#include "screen.h" #include "screen.h"
@@ -16,10 +17,16 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <signal.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <signal.h>
extern PyTypeObject Screen_Type; extern PyTypeObject Screen_Type;
#ifdef DEBUG_EVENT_LOOP
#define EVDBG(...) log_event(__VA_ARGS__)
#else
#define EVDBG(...)
#endif
#define EXTRA_FDS 2 #define EXTRA_FDS 2
#ifndef MSG_NOSIGNAL #ifndef MSG_NOSIGNAL
// Apple does not implement MSG_NOSIGNAL // Apple does not implement MSG_NOSIGNAL
@@ -46,6 +53,7 @@ typedef struct {
int talk_fd, listen_fd; int talk_fd, listen_fd;
Message *messages; Message *messages;
size_t messages_capacity, messages_count; size_t messages_capacity, messages_count;
LoopData io_loop_data;
} ChildMonitor; } ChildMonitor;
@@ -77,7 +85,6 @@ static pthread_mutex_t children_lock;
static bool kill_signal_received = false; static bool kill_signal_received = false;
static ChildMonitor *the_monitor = NULL; static ChildMonitor *the_monitor = NULL;
static uint8_t drain_buf[1024]; static uint8_t drain_buf[1024];
static int signal_fds[2], wakeup_fds[2];
typedef struct { typedef struct {
@@ -110,39 +117,6 @@ set_maximum_wait(double val) {
if (val >= 0 && (val < maximum_wait || maximum_wait < 0)) maximum_wait = val; if (val >= 0 && (val < maximum_wait || maximum_wait < 0)) maximum_wait = val;
} }
static void
handle_signal(int sig_num) {
int save_err = errno;
unsigned char byte = (unsigned char)sig_num;
while(true) {
ssize_t ret = write(signal_fds[1], &byte, 1);
if (ret < 0 && errno == EINTR) continue;
break;
}
errno = save_err;
}
static inline bool
self_pipe(int fds[2]) {
#ifdef __APPLE__
int flags;
flags = pipe(fds);
if (flags != 0) return false;
for (int i = 0; i < 2; i++) {
flags = fcntl(fds[i], F_GETFD);
if (flags == -1) { return false; }
if (fcntl(fds[i], F_SETFD, flags | FD_CLOEXEC) == -1) { return false; }
flags = fcntl(fds[i], F_GETFL);
if (flags == -1) { return false; }
if (fcntl(fds[i], F_SETFL, flags | O_NONBLOCK) == -1) { return false; }
}
return true;
#else
return pipe2(fds, O_CLOEXEC | O_NONBLOCK) == 0;
#endif
}
static PyObject * static PyObject *
new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) { new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
ChildMonitor *self; ChildMonitor *self;
@@ -156,13 +130,9 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret)); PyErr_Format(PyExc_RuntimeError, "Failed to create children_lock mutex: %s", strerror(ret));
return NULL; return NULL;
} }
if (!self_pipe(wakeup_fds)) return PyErr_SetFromErrno(PyExc_OSError);
if (!self_pipe(signal_fds)) return PyErr_SetFromErrno(PyExc_OSError);
struct sigaction act = {.sa_handler=handle_signal};
#define SA(which) { if (sigaction(which, &act, NULL) != 0) return PyErr_SetFromErrno(PyExc_OSError); if (siginterrupt(which, false) != 0) return PyErr_SetFromErrno(PyExc_OSError);}
SA(SIGINT); SA(SIGTERM); SA(SIGCHLD);
#undef SA
self = (ChildMonitor *)type->tp_alloc(type, 0); self = (ChildMonitor *)type->tp_alloc(type, 0);
if (!init_loop_data(&self->io_loop_data)) return PyErr_SetFromErrno(PyExc_OSError);
if (!install_signal_handlers(&self->io_loop_data)) return PyErr_SetFromErrno(PyExc_OSError);
self->talk_fd = talk_fd; self->talk_fd = talk_fd;
self->listen_fd = listen_fd; self->listen_fd = listen_fd;
if (self == NULL) return PyErr_NoMemory(); if (self == NULL) return PyErr_NoMemory();
@@ -172,7 +142,7 @@ new(PyTypeObject *type, PyObject *args, PyObject UNUSED *kwds) {
parse_func = parse_worker_dump; parse_func = parse_worker_dump;
} else parse_func = parse_worker; } else parse_func = parse_worker;
self->count = 0; self->count = 0;
fds[0].fd = wakeup_fds[0]; fds[1].fd = signal_fds[0]; fds[0].fd = self->io_loop_data.wakeup_read_fd; fds[1].fd = self->io_loop_data.signal_read_fd;
fds[0].events = POLLIN; fds[1].events = POLLIN; fds[0].events = POLLIN; fds[1].events = POLLIN;
the_monitor = self; the_monitor = self;
@@ -193,22 +163,12 @@ dealloc(ChildMonitor* self) {
add_queue_count--; add_queue_count--;
FREE_CHILD(add_queue[add_queue_count]); FREE_CHILD(add_queue[add_queue_count]);
} }
close(wakeup_fds[0]); free_loop_data(&self->io_loop_data);
close(wakeup_fds[1]);
close(signal_fds[0]);
close(signal_fds[1]);
} }
void static void
wakeup_io_loop(bool in_signal_handler) { wakeup_io_loop(ChildMonitor *self, bool in_signal_handler) {
while(true) { wakeup_loop(&self->io_loop_data, in_signal_handler, "io_loop");
ssize_t ret = write(wakeup_fds[1], "w", 1);
if (ret < 0) {
if (errno == EINTR) continue;
if (!in_signal_handler) perror("Failed to write to wakeup fd with error");
}
break;
}
} }
static void* io_loop(void *data); static void* io_loop(void *data);
@@ -231,11 +191,10 @@ start(PyObject *s, PyObject *a UNUSED) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static PyObject * static PyObject *
wakeup(PYNOARG) { wakeup(ChildMonitor *self, PyObject *args UNUSED) {
#define wakeup_doc "wakeup() -> wakeup the ChildMonitor I/O thread, forcing it to exit from poll() if it is waiting there." #define wakeup_doc "wakeup() -> wakeup the ChildMonitor I/O thread, forcing it to exit from poll() if it is waiting there."
wakeup_io_loop(false); wakeup_io_loop(self, false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -254,7 +213,7 @@ add_child(ChildMonitor *self, PyObject *args) {
INCREF_CHILD(add_queue[add_queue_count]); INCREF_CHILD(add_queue[add_queue_count]);
add_queue_count++; add_queue_count++;
children_mutex(unlock); children_mutex(unlock);
wakeup_io_loop(false); wakeup_io_loop(self, false);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -301,7 +260,7 @@ schedule_write_to_child(unsigned long id, unsigned int num, ...) {
screen->write_buf = PyMem_RawRealloc(screen->write_buf, screen->write_buf_sz); screen->write_buf = PyMem_RawRealloc(screen->write_buf, screen->write_buf_sz);
if (screen->write_buf == NULL) { fatal("Out of memory."); } if (screen->write_buf == NULL) { fatal("Out of memory."); }
} }
if (screen->write_buf_used) wakeup_io_loop(false); if (screen->write_buf_used) wakeup_io_loop(self, false);
screen_mutex(unlock, write); screen_mutex(unlock, write);
break; break;
} }
@@ -323,12 +282,9 @@ needs_write(ChildMonitor UNUSED *self, PyObject *args) {
static PyObject * static PyObject *
shutdown_monitor(ChildMonitor *self, PyObject *a UNUSED) { shutdown_monitor(ChildMonitor *self, PyObject *a UNUSED) {
#define shutdown_monitor_doc "shutdown_monitor() -> Shutdown the monitor loop." #define shutdown_monitor_doc "shutdown_monitor() -> Shutdown the monitor loop."
signal(SIGINT, SIG_DFL);
signal(SIGTERM, SIG_DFL);
signal(SIGCHLD, SIG_DFL);
self->shutting_down = true; self->shutting_down = true;
wakeup_talk_loop(false); wakeup_talk_loop(false);
wakeup_io_loop(false); wakeup_io_loop(self, false);
int ret = pthread_join(self->io_thread, NULL); int ret = pthread_join(self->io_thread, NULL);
if (ret != 0) return PyErr_Format(PyExc_OSError, "Failed to join() I/O thread with error: %s", strerror(ret)); if (ret != 0) return PyErr_Format(PyExc_OSError, "Failed to join() I/O thread with error: %s", strerror(ret));
if (talk_thread_started) { if (talk_thread_started) {
@@ -339,15 +295,17 @@ shutdown_monitor(ChildMonitor *self, PyObject *a UNUSED) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
static inline void static inline bool
do_parse(ChildMonitor *self, Screen *screen, double now) { do_parse(ChildMonitor *self, Screen *screen, double now) {
bool input_read = false;
screen_mutex(lock, read); screen_mutex(lock, read);
if (screen->read_buf_sz || screen->pending_mode.used) { if (screen->read_buf_sz || screen->pending_mode.used) {
double time_since_new_input = now - screen->new_input_at; double time_since_new_input = now - screen->new_input_at;
if (time_since_new_input >= OPT(input_delay)) { if (time_since_new_input >= OPT(input_delay)) {
bool read_buf_full = screen->read_buf_sz >= READ_BUF_SZ; bool read_buf_full = screen->read_buf_sz >= READ_BUF_SZ;
input_read = true;
parse_func(screen, self->dump_callback, now); parse_func(screen, self->dump_callback, now);
if (read_buf_full) wakeup_io_loop(false); // Ensure the read fd has POLLIN set if (read_buf_full) wakeup_io_loop(self, false); // Ensure the read fd has POLLIN set
screen->new_input_at = 0; screen->new_input_at = 0;
if (screen->pending_mode.activated_at) { if (screen->pending_mode.activated_at) {
double time_since_pending = MAX(0, now - screen->pending_mode.activated_at); double time_since_pending = MAX(0, now - screen->pending_mode.activated_at);
@@ -356,12 +314,14 @@ do_parse(ChildMonitor *self, Screen *screen, double now) {
} else set_maximum_wait(OPT(input_delay) - time_since_new_input); } else set_maximum_wait(OPT(input_delay) - time_since_new_input);
} }
screen_mutex(unlock, read); screen_mutex(unlock, read);
return input_read;
} }
static void static bool
parse_input(ChildMonitor *self) { parse_input(ChildMonitor *self) {
// Parse all available input that was read in the I/O thread. // Parse all available input that was read in the I/O thread.
size_t count = 0, remove_count = 0; size_t count = 0, remove_count = 0;
bool input_read = false;
double now = monotonic(); double now = monotonic();
PyObject *msg = NULL; PyObject *msg = NULL;
children_mutex(lock); children_mutex(lock);
@@ -416,10 +376,11 @@ parse_input(ChildMonitor *self) {
for (size_t i = 0; i < count; i++) { for (size_t i = 0; i < count; i++) {
if (!scratch[i].needs_removal) { if (!scratch[i].needs_removal) {
do_parse(self, scratch[i].screen, now); if (do_parse(self, scratch[i].screen, now)) input_read = true;
} }
DECREF_CHILD(scratch[i]); DECREF_CHILD(scratch[i]);
} }
return input_read;
} }
static inline void static inline void
@@ -432,7 +393,7 @@ mark_child_for_close(ChildMonitor *self, id_type window_id) {
} }
} }
children_mutex(unlock); children_mutex(unlock);
wakeup_io_loop(false); wakeup_io_loop(self, false);
} }
@@ -521,9 +482,7 @@ pyset_iutf8(ChildMonitor *self, PyObject *args) {
#undef INCREF_CHILD #undef INCREF_CHILD
#undef DECREF_CHILD #undef DECREF_CHILD
static double last_render_at = -DBL_MAX; extern void cocoa_update_menu_bar_title(PyObject*);
extern void cocoa_update_title(PyObject*);
static inline void static inline void
collect_cursor_info(CursorRenderInfo *ans, Window *w, double now, OSWindow *os_window) { collect_cursor_info(CursorRenderInfo *ans, Window *w, double now, OSWindow *os_window) {
@@ -559,7 +518,7 @@ update_window_title(Window *w, OSWindow *os_window) {
Py_INCREF(os_window->window_title); Py_INCREF(os_window->window_title);
set_os_window_title(os_window, PyUnicode_AsUTF8(w->title)); set_os_window_title(os_window, PyUnicode_AsUTF8(w->title));
#ifdef __APPLE__ #ifdef __APPLE__
if (os_window->is_focused && OPT(macos_show_window_title_in_menubar)) cocoa_update_title(w->title); if (os_window->is_focused && (OPT(macos_show_window_title_in) & MENUBAR)) cocoa_update_menu_bar_title(w->title);
#endif #endif
return true; return true;
} }
@@ -567,7 +526,7 @@ update_window_title(Window *w, OSWindow *os_window) {
} }
static inline bool 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, double now, unsigned int *active_window_id, color_type *active_window_bg, unsigned int *num_visible_windows, bool *all_windows_have_same_bg) {
#define TD os_window->tab_bar_render_data #define TD os_window->tab_bar_render_data
bool needs_render = os_window->needs_render; bool needs_render = os_window->needs_render;
os_window->needs_render = false; os_window->needs_render = false;
@@ -584,11 +543,17 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
} }
Tab *tab = os_window->tabs + os_window->active_tab; Tab *tab = os_window->tabs + os_window->active_tab;
*active_window_bg = OPT(background); *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++) { for (unsigned int i = 0; i < tab->num_windows; i++) {
Window *w = tab->windows + i; Window *w = tab->windows + i;
#define WD w->render_data #define WD w->render_data
if (w->visible && WD.screen) { if (w->visible && WD.screen) {
*num_visible_windows += 1; *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 (w->last_drag_scroll_at > 0) {
if (now - w->last_drag_scroll_at >= 0.02) { if (now - w->last_drag_scroll_at >= 0.02) {
if (drag_scroll(w, os_window)) { if (drag_scroll(w, os_window)) {
@@ -604,7 +569,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); collect_cursor_info(&WD.screen->cursor_render_info, w, now, os_window);
if (w->cursor_visible_at_last_render != WD.screen->cursor_render_info.is_visible || w->last_cursor_x != WD.screen->cursor_render_info.x || w->last_cursor_y != WD.screen->cursor_render_info.y || w->last_cursor_shape != WD.screen->cursor_render_info.shape) needs_render = true; if (w->cursor_visible_at_last_render != WD.screen->cursor_render_info.is_visible || w->last_cursor_x != WD.screen->cursor_render_info.x || w->last_cursor_y != WD.screen->cursor_render_info.y || w->last_cursor_shape != WD.screen->cursor_render_info.shape) needs_render = true;
update_window_title(w, os_window); 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; } else WD.screen->cursor_render_info.is_visible = false;
if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true; if (send_cell_data_to_gpu(WD.vao_idx, WD.gvao_idx, WD.xstart, WD.ystart, WD.dx, WD.dy, WD.screen, os_window)) needs_render = true;
if (WD.screen->start_visual_bell_at != 0) needs_render = true; if (WD.screen->start_visual_bell_at != 0) needs_render = true;
@@ -614,7 +579,7 @@ prepare_to_render_os_window(OSWindow *os_window, double now, unsigned int *activ
} }
static inline void 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, double 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 // 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); if (os_window->clear_count++ < 3) blank_os_window(os_window);
Tab *tab = os_window->tabs + os_window->active_tab; Tab *tab = os_window->tabs + os_window->active_tab;
@@ -626,7 +591,7 @@ render_os_window(OSWindow *os_window, double now, unsigned int active_window_id,
y_ratio = os_window->viewport_height / (double) os_window->live_resize.height; y_ratio = os_window->viewport_height / (double) os_window->live_resize.height;
} }
if (!static_live_resize_in_progress) { 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; 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); 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);
@@ -636,7 +601,7 @@ render_os_window(OSWindow *os_window, double now, unsigned int active_window_id,
bool is_active_window = i == tab->active_window; 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); 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) { if (WD.screen->start_visual_bell_at != 0) {
double bell_left = global_state.opts.visual_bell_duration - (now - WD.screen->start_visual_bell_at); double bell_left = OPT(visual_bell_duration) - (now - WD.screen->start_visual_bell_at);
set_maximum_wait(bell_left); 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; 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;
@@ -672,10 +637,19 @@ draw_resizing_text(OSWindow *w) {
} }
} }
static inline bool
no_render_frame_received_recently(OSWindow *w, double now, double 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);
return ans;
}
static inline void static inline void
render(double now) { render(double 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; double time_since_last_render = now - last_render_at;
if (time_since_last_render < OPT(repaint_delay)) { if (!input_read && time_since_last_render < OPT(repaint_delay)) {
set_maximum_wait(OPT(repaint_delay) - time_since_last_render); set_maximum_wait(OPT(repaint_delay) - time_since_last_render);
return; return;
} }
@@ -688,7 +662,7 @@ render(double now) {
continue; continue;
} }
if (USE_RENDER_FRAMES && w->render_state != RENDER_FRAME_READY) { if (USE_RENDER_FRAMES && w->render_state != RENDER_FRAME_READY) {
if (w->render_state == RENDER_FRAME_NOT_REQUESTED) request_frame_render(w); if (w->render_state == RENDER_FRAME_NOT_REQUESTED || no_render_frame_received_recently(w, now, 0.25)) request_frame_render(w);
continue; continue;
} }
make_os_window_context_current(w); make_os_window_context_current(w);
@@ -708,11 +682,12 @@ render(double now) {
needs_render = true; needs_render = true;
} }
unsigned int active_window_id = 0, num_visible_windows = 0; unsigned int active_window_id = 0, num_visible_windows = 0;
bool all_windows_have_same_bg;
color_type active_window_bg = 0; color_type active_window_bg = 0;
if (!w->fonts_data) { log_error("No fonts data found for window id: %llu", w->id); continue; } 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 (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; last_render_at = now;
#undef TD #undef TD
@@ -723,7 +698,7 @@ typedef struct { int fd; uint8_t *buf; size_t sz; } ThreadWriteData;
static inline ThreadWriteData* static inline ThreadWriteData*
alloc_twd(size_t sz) { alloc_twd(size_t sz) {
ThreadWriteData *data = malloc(sizeof(ThreadWriteData)); ThreadWriteData *data = calloc(1, sizeof(ThreadWriteData));
if (data != NULL) { if (data != NULL) {
data->sz = sz; data->sz = sz;
data->buf = malloc(sz); data->buf = malloc(sz);
@@ -771,11 +746,25 @@ static void*
thread_write(void *x) { thread_write(void *x) {
ThreadWriteData *data = (ThreadWriteData*)x; ThreadWriteData *data = (ThreadWriteData*)x;
set_thread_name("KittyWriteStdin"); set_thread_name("KittyWriteStdin");
FILE *f = fdopen(data->fd, "w"); int flags = fcntl(data->fd, F_GETFL, 0);
if (fwrite(data->buf, 1, data->sz, f) != data->sz) { if (flags == -1) { free_twd(data); return 0; }
log_error("Failed to write all data"); flags &= ~O_NONBLOCK;
fcntl(data->fd, F_SETFL, flags);
size_t pos = 0;
while (pos < data->sz) {
errno = 0;
ssize_t nbytes = write(data->fd, data->buf + pos, data->sz - pos);
if (nbytes < 0) {
if (errno == EAGAIN || errno == EINTR) continue;
break;
}
if (nbytes == 0) break;
pos += nbytes;
} }
fclose(f); if (pos < data->sz) {
log_error("Failed to write all data to STDIN of child process with error: %s", strerror(errno));
}
safe_close(data->fd);
free_twd(data); free_twd(data);
return 0; return 0;
} }
@@ -792,7 +781,8 @@ cm_thread_write(PyObject UNUSED *self, PyObject *args) {
data->fd = fd; data->fd = fd;
memcpy(data->buf, buf, data->sz); memcpy(data->buf, buf, data->sz);
int ret = pthread_create(&thread, NULL, thread_write, data); int ret = pthread_create(&thread, NULL, thread_write, data);
if (ret != 0) { free_twd(data); return PyErr_SetFromErrno(PyExc_OSError); } if (ret != 0) { safe_close(fd); free_twd(data); return PyErr_SetFromErrno(PyExc_OSError); }
pthread_detach(thread);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@@ -913,21 +903,23 @@ static void process_global_state(void *data);
static void static void
do_state_check(id_type timer_id UNUSED, void *data) { do_state_check(id_type timer_id UNUSED, void *data) {
ChildMonitor *self = data; EVDBG("State check timer fired");
process_global_state(self); process_global_state(data);
} }
static id_type state_check_timer = 0; static id_type state_check_timer = 0;
static void static void
process_global_state(void *data) { process_global_state(void *data) {
EVDBG("Processing global state");
ChildMonitor *self = data; ChildMonitor *self = data;
maximum_wait = -1; maximum_wait = -1;
bool state_check_timer_enabled = false; bool state_check_timer_enabled = false;
double now = monotonic(); double now = monotonic();
if (global_state.has_pending_resizes) process_pending_resizes(now); if (global_state.has_pending_resizes) process_pending_resizes(now);
render(now); bool input_read = parse_input(self);
render(now, input_read);
#ifdef __APPLE__ #ifdef __APPLE__
if (cocoa_pending_actions) { if (cocoa_pending_actions) {
if (cocoa_pending_actions & PREFERENCES_WINDOW) { call_boss(edit_config_file, NULL); } if (cocoa_pending_actions & PREFERENCES_WINDOW) { call_boss(edit_config_file, NULL); }
@@ -941,7 +933,6 @@ process_global_state(void *data) {
cocoa_pending_actions = 0; cocoa_pending_actions = 0;
} }
#endif #endif
parse_input(self);
if (global_state.terminate) { if (global_state.terminate) {
global_state.terminate = false; global_state.terminate = false;
close_all_windows(); close_all_windows();
@@ -954,7 +945,8 @@ process_global_state(void *data) {
if (global_state.has_pending_closes) has_open_windows = process_pending_closes(self); if (global_state.has_pending_closes) has_open_windows = process_pending_closes(self);
if (has_open_windows) { if (has_open_windows) {
if (maximum_wait >= 0) { if (maximum_wait >= 0) {
state_check_timer_enabled = true; if (maximum_wait == 0) request_tick_callback();
else state_check_timer_enabled = true;
} }
} else { } else {
stop_main_loop(); stop_main_loop();
@@ -1005,7 +997,7 @@ hangup(pid_t pid) {
static inline void static inline void
cleanup_child(ssize_t i) { cleanup_child(ssize_t i) {
close(children[i].fd); safe_close(children[i].fd);
hangup(children[i].pid); hangup(children[i].pid);
} }
@@ -1074,35 +1066,28 @@ drain_fd(int fd) {
ssize_t len = read(fd, drain_buf, sizeof(drain_buf)); ssize_t len = read(fd, drain_buf, sizeof(drain_buf));
if (len < 0) { if (len < 0) {
if (errno == EINTR) continue; if (errno == EINTR) continue;
if (errno != EIO) perror("Call to read() from drain fd failed");
break; break;
} }
if (len > 0) continue;
break; break;
} }
} }
static inline void typedef struct { bool kill_signal, child_died; } SignalSet;
read_signals(int fd, bool *kill_signal, bool *child_died) {
static char buf[256]; static void
while(true) { handle_signal(int signum, void *data) {
ssize_t len = read(fd, buf, sizeof(buf)); SignalSet *ss = data;
if (len < 0) { switch(signum) {
if (errno == EINTR) continue; case SIGINT:
if (errno != EIO) perror("Call to read() from read_signals() failed"); case SIGTERM:
ss->kill_signal = true;
break;
case SIGCHLD:
ss->child_died = true;
break;
default:
break; break;
}
for (ssize_t i = 0; i < len; i++) {
switch(buf[i]) {
case SIGCHLD:
*child_died = true; break;
case SIGINT:
case SIGTERM:
*kill_signal = true; break;
default:
break;
}
}
break;
} }
} }
@@ -1212,11 +1197,11 @@ io_loop(void *data) {
if (ret > 0) { if (ret > 0) {
if (fds[0].revents && POLLIN) drain_fd(fds[0].fd); // wakeup if (fds[0].revents && POLLIN) drain_fd(fds[0].fd); // wakeup
if (fds[1].revents && POLLIN) { if (fds[1].revents && POLLIN) {
SignalSet ss = {0};
data_received = true; data_received = true;
bool kill_signal = false, child_died = false; read_signals(fds[1].fd, handle_signal, &ss);
read_signals(fds[1].fd, &kill_signal, &child_died); if (ss.kill_signal) { children_mutex(lock); kill_signal_received = true; children_mutex(unlock); }
if (kill_signal) { children_mutex(lock); kill_signal_received = true; children_mutex(unlock); } if (ss.child_died) reap_children(self, OPT(close_on_child_death));
if (child_died) reap_children(self, OPT(close_on_child_death));
} }
for (i = 0; i < self->count; i++) { for (i = 0; i < self->count; i++) {
if (fds[EXTRA_FDS + i].revents & (POLLIN | POLLHUP)) { if (fds[EXTRA_FDS + i].revents & (POLLIN | POLLHUP)) {
@@ -1296,14 +1281,14 @@ typedef struct {
PeerReadData *reads; PeerReadData *reads;
PeerWriteData *writes; PeerWriteData *writes;
PeerWriteData *queued_writes; PeerWriteData *queued_writes;
int wakeup_fds[2]; LoopData loop_data;
pthread_mutex_t peer_lock; pthread_mutex_t peer_lock;
} TalkData; } TalkData;
static TalkData talk_data = {0}; static TalkData talk_data = {0};
typedef struct pollfd PollFD; typedef struct pollfd PollFD;
#define PEER_LIMIT 256 #define PEER_LIMIT 256
#define nuke_socket(s) { shutdown(s, SHUT_RDWR); close(s); } #define nuke_socket(s) { shutdown(s, SHUT_RDWR); safe_close(s); }
static inline bool static inline bool
accept_peer(int listen_fd, bool shutting_down) { accept_peer(int listen_fd, bool shutting_down) {
@@ -1336,7 +1321,7 @@ read_from_peer(ChildMonitor *self, int s) {
if (rd->fd == s) { if (rd->fd == s) {
if (rd->used >= rd->capacity) { if (rd->used >= rd->capacity) {
if (rd->capacity >= 1024 * 1024) failed("Ignoring too large message from peer"); if (rd->capacity >= 1024 * 1024) failed("Ignoring too large message from peer");
rd->capacity = MAX(8192, rd->capacity * 2); rd->capacity = MAX(8192u, rd->capacity * 2);
rd->data = realloc(rd->data, rd->capacity); rd->data = realloc(rd->data, rd->capacity);
if (!rd->data) failed("Out of memory"); if (!rd->data) failed("Out of memory");
} }
@@ -1424,7 +1409,7 @@ prune_finished_writes(void) {
PeerWriteData *wd = talk_data.writes + i; PeerWriteData *wd = talk_data.writes + i;
if (wd->finished) { if (wd->finished) {
remove_poll_fd(wd->fd); remove_poll_fd(wd->fd);
shutdown(wd->fd, SHUT_WR); close(wd->fd); shutdown(wd->fd, SHUT_WR); safe_close(wd->fd);
free(wd->data); free(wd->data);
ssize_t num_to_right = talk_data.num_writes - 1 - i; ssize_t num_to_right = talk_data.num_writes - 1 - i;
if (num_to_right > 0) memmove(talk_data.writes + i, talk_data.writes + i + 1, num_to_right * sizeof(PeerWriteData)); if (num_to_right > 0) memmove(talk_data.writes + i, talk_data.writes + i + 1, num_to_right * sizeof(PeerWriteData));
@@ -1436,15 +1421,7 @@ prune_finished_writes(void) {
static void static void
wakeup_talk_loop(bool in_signal_handler) { wakeup_talk_loop(bool in_signal_handler) {
if (talk_data.wakeup_fds[1] <= 0) return; if (talk_thread_started) wakeup_loop(&talk_data.loop_data, in_signal_handler, "talk_loop");
while(true) {
ssize_t ret = write(talk_data.wakeup_fds[1], "w", 1);
if (ret < 0) {
if (errno == EINTR) continue;
if (!in_signal_handler) perror("Failed to write to talk wakeup fd with error");
}
break;
}
} }
static inline void static inline void
@@ -1473,7 +1450,7 @@ talk_loop(void *data) {
ChildMonitor *self = (ChildMonitor*)data; ChildMonitor *self = (ChildMonitor*)data;
set_thread_name("KittyPeerMon"); set_thread_name("KittyPeerMon");
if ((pthread_mutex_init(&talk_data.peer_lock, NULL)) != 0) { perror("Failed to create peer mutex"); return 0; } if ((pthread_mutex_init(&talk_data.peer_lock, NULL)) != 0) { perror("Failed to create peer mutex"); return 0; }
if (!self_pipe(talk_data.wakeup_fds)) { perror("Failed to create wakeup fds for talk thread"); return 0; } if (!init_loop_data(&talk_data.loop_data)) { log_error("Failed to create wakeup fd for talk thread with error: %s", strerror(errno)); }
ensure_space_for(&talk_data, fds, PollFD, 8, fds_capacity, 8, false); ensure_space_for(&talk_data, fds, PollFD, 8, fds_capacity, 8, false);
#define add_listener(which) \ #define add_listener(which) \
if (self->which > -1) { \ if (self->which > -1) { \
@@ -1481,7 +1458,7 @@ talk_loop(void *data) {
} }
add_listener(talk_fd); add_listener(listen_fd); add_listener(talk_fd); add_listener(listen_fd);
#undef add_listener #undef add_listener
talk_data.fds[talk_data.num_listen_fds].fd = talk_data.wakeup_fds[0]; talk_data.fds[talk_data.num_listen_fds++].events = POLLIN; talk_data.fds[talk_data.num_listen_fds].fd = talk_data.loop_data.wakeup_read_fd; talk_data.fds[talk_data.num_listen_fds++].events = POLLIN;
while (LIKELY(!self->shutting_down)) { while (LIKELY(!self->shutting_down)) {
for (size_t i = 0; i < talk_data.num_listen_fds + talk_data.num_talk_fds; i++) { talk_data.fds[i].revents = 0; } for (size_t i = 0; i < talk_data.num_listen_fds + talk_data.num_talk_fds; i++) { talk_data.fds[i].revents = 0; }
@@ -1504,7 +1481,7 @@ talk_loop(void *data) {
} else if (ret < 0) { if (errno != EAGAIN && errno != EINTR) perror("poll() on talk fds failed"); } } else if (ret < 0) { if (errno != EAGAIN && errno != EINTR) perror("poll() on talk fds failed"); }
} }
end: end:
close(talk_data.wakeup_fds[0]); close(talk_data.wakeup_fds[1]); free_loop_data(&talk_data.loop_data);
free(talk_data.fds); free(talk_data.reads); free(talk_data.writes); free(talk_data.queued_writes); free(talk_data.fds); free(talk_data.reads); free(talk_data.writes); free(talk_data.queued_writes);
return 0; return 0;
} }
@@ -1530,8 +1507,8 @@ add_peer_writer(int fd, const char* msg, size_t msg_sz) {
static void static void
send_response(int fd, const char *msg, size_t msg_sz) { send_response(int fd, const char *msg, size_t msg_sz) {
if (msg == NULL) { shutdown(fd, SHUT_WR); close(fd); return; } if (msg == NULL) { shutdown(fd, SHUT_WR); safe_close(fd); return; }
if (!add_peer_writer(fd, msg, msg_sz)) { shutdown(fd, SHUT_WR); close(fd); } if (!add_peer_writer(fd, msg, msg_sz)) { shutdown(fd, SHUT_WR); safe_close(fd); }
else wakeup_talk_loop(false); else wakeup_talk_loop(false);
} }
@@ -1565,18 +1542,20 @@ PyTypeObject ChildMonitor_Type = {
static PyObject* static PyObject*
safe_pipe(PYNOARG) { safe_pipe(PyObject *self UNUSED, PyObject *args) {
int nonblock = 1;
if (!PyArg_ParseTuple(args, "|p", &nonblock)) return NULL;
int fds[2] = {0}; int fds[2] = {0};
if (!self_pipe(fds)) return PyErr_SetFromErrno(PyExc_OSError); if (!self_pipe(fds, nonblock)) return PyErr_SetFromErrno(PyExc_OSError);
return Py_BuildValue("ii", fds[0], fds[1]); return Py_BuildValue("ii", fds[0], fds[1]);
} }
static PyMethodDef module_methods[] = { static PyMethodDef module_methods[] = {
METHODB(safe_pipe, METH_NOARGS), METHODB(safe_pipe, METH_VARARGS),
{"add_timer", (PyCFunction)add_python_timer, METH_VARARGS, ""}, {"add_timer", (PyCFunction)add_python_timer, METH_VARARGS, ""},
{"remove_timer", (PyCFunction)remove_python_timer, METH_VARARGS, ""}, {"remove_timer", (PyCFunction)remove_python_timer, METH_VARARGS, ""},
METHODB(monitor_pid, METH_VARARGS), METHODB(monitor_pid, METH_VARARGS),
{"set_iutf8", (PyCFunction)pyset_iutf8, METH_VARARGS, ""}, {"set_iutf8_winid", (PyCFunction)pyset_iutf8, METH_VARARGS, ""},
{NULL} /* Sentinel */ {NULL} /* Sentinel */
}; };

View File

@@ -78,8 +78,14 @@ spawn(PyObject *self UNUSED, PyObject *args) {
pid_t pid = fork(); pid_t pid = fork();
switch(pid) { switch(pid) {
case 0: case 0: {
// child // child
sigset_t signals = {0};
struct sigaction act = {.sa_handler=SIG_DFL};
#define SA(which) { if (sigaction(which, &act, NULL) != 0) exit_on_err("sigaction() in child process failed"); }
SA(SIGINT); SA(SIGTERM); SA(SIGCHLD);
#undef SA
if (sigprocmask(SIG_SETMASK, &signals, NULL) != 0) exit_on_err("sigprocmask() in child process failed");
// Use only signal-safe functions (man 7 signal-safety) // Use only signal-safe functions (man 7 signal-safety)
if (chdir(cwd) != 0) { if (chdir("/") != 0) {} }; // ignore failure to chdir to / if (chdir(cwd) != 0) { if (chdir("/") != 0) {} }; // ignore failure to chdir to /
if (setsid() == -1) exit_on_err("setsid() in child process failed"); if (setsid() == -1) exit_on_err("setsid() in child process failed");
@@ -91,28 +97,28 @@ spawn(PyObject *self UNUSED, PyObject *args) {
// On BSD open() does not establish the controlling terminal // On BSD open() does not establish the controlling terminal
if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY"); if (ioctl(tfd, TIOCSCTTY, 0) == -1) exit_on_err("Failed to set controlling terminal with TIOCSCTTY");
#endif #endif
close(tfd); safe_close(tfd);
// Redirect stdin/stdout/stderr to the pty // Redirect stdin/stdout/stderr to the pty
if (dup2(slave, 1) == -1) exit_on_err("dup2() failed for fd number 1"); if (dup2(slave, 1) == -1) exit_on_err("dup2() failed for fd number 1");
if (dup2(slave, 2) == -1) exit_on_err("dup2() failed for fd number 2"); if (dup2(slave, 2) == -1) exit_on_err("dup2() failed for fd number 2");
if (stdin_read_fd > -1) { if (stdin_read_fd > -1) {
if (dup2(stdin_read_fd, 0) == -1) exit_on_err("dup2() failed for fd number 0"); if (dup2(stdin_read_fd, 0) == -1) exit_on_err("dup2() failed for fd number 0");
close(stdin_read_fd); safe_close(stdin_read_fd);
close(stdin_write_fd); safe_close(stdin_write_fd);
} else { } else {
if (dup2(slave, 0) == -1) exit_on_err("dup2() failed for fd number 0"); if (dup2(slave, 0) == -1) exit_on_err("dup2() failed for fd number 0");
} }
close(slave); safe_close(slave);
close(master); safe_close(master);
// Wait for READY_SIGNAL which indicates kitty has setup the screen object // Wait for READY_SIGNAL which indicates kitty has setup the screen object
close(ready_write_fd); safe_close(ready_write_fd);
wait_for_terminal_ready(ready_read_fd); wait_for_terminal_ready(ready_read_fd);
close(ready_read_fd); safe_close(ready_read_fd);
// Close any extra fds inherited from parent // Close any extra fds inherited from parent
for (int c = 3; c < 201; c++) close(c); for (int c = 3; c < 201; c++) safe_close(c);
environ = env; environ = env;
// for some reason SIGPIPE is set to SIG_IGN, so reset it, needed by bash, // for some reason SIGPIPE is set to SIG_IGN, so reset it, needed by bash,
@@ -129,6 +135,7 @@ spawn(PyObject *self UNUSED, PyObject *args) {
execlp("sh", "sh", "-c", "read w", NULL); execlp("sh", "sh", "-c", "read w", NULL);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
break; break;
}
case -1: case -1:
PyErr_SetFromErrno(PyExc_OSError); PyErr_SetFromErrno(PyExc_OSError);
break; break;

View File

@@ -30,14 +30,16 @@ if is_macos:
else: else:
def cmdline_of_process(pid): 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): def cwd_of_process(pid):
ans = '/proc/{}/cwd'.format(pid) ans = '/proc/{}/cwd'.format(pid)
return os.path.realpath(ans) return os.path.realpath(ans)
def _environ_of_process(pid): 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(): def process_group_map():
ans = defaultdict(list) ans = defaultdict(list)
@@ -47,7 +49,8 @@ else:
except Exception: except Exception:
continue continue
try: try:
raw = open('/proc/' + x + '/stat', 'rb').read().decode('utf-8') with open('/proc/' + x + '/stat', 'rb') as f:
raw = f.read().decode('utf-8')
except EnvironmentError: except EnvironmentError:
continue continue
try: try:
@@ -118,6 +121,10 @@ def remove_cloexec(fd):
fcntl.fcntl(fd, fcntl.F_SETFD, fcntl.fcntl(fd, fcntl.F_GETFD) & ~fcntl.FD_CLOEXEC) 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 default_env(): def default_env():
try: try:
return default_env.env return default_env.env
@@ -132,6 +139,13 @@ def set_default_env(val=None):
default_env.env = env 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: class Child:
child_fd = pid = None child_fd = pid = None
@@ -166,7 +180,7 @@ class Child:
env['TERM'] = self.opts.term env['TERM'] = self.opts.term
env['COLORTERM'] = 'truecolor' env['COLORTERM'] = 'truecolor'
if self.cwd: 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 # can use it to display the current directory name rather
# than the resolved path # than the resolved path
env['PWD'] = self.cwd env['PWD'] = self.cwd
@@ -178,9 +192,7 @@ class Child:
if self.forked: if self.forked:
return return
self.forked = True self.forked = True
master, slave = os.openpty() # Note that master and slave are in blocking mode master, slave = openpty()
remove_cloexec(slave)
fast_data_types.set_iutf8(master, True)
stdin, self.stdin = self.stdin, None stdin, self.stdin = self.stdin, None
ready_read_fd, ready_write_fd = os.pipe() ready_read_fd, ready_write_fd = os.pipe()
remove_cloexec(ready_read_fd) remove_cloexec(ready_read_fd)
@@ -194,8 +206,20 @@ class Child:
argv = list(self.argv) argv = list(self.argv)
exe = argv[0] exe = argv[0]
if is_macos and exe == shell_path: if is_macos and exe == shell_path:
# Some macOS machines need the shell to have argv[0] prefixed by # bash will only source ~/.bash_profile if it detects it is a login
# hyphen, see https://github.com/kovidgoyal/kitty/issues/247 # 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]) 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) 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) os.close(slave)
@@ -206,7 +230,7 @@ class Child:
fast_data_types.thread_write(stdin_write_fd, stdin) fast_data_types.thread_write(stdin_write_fd, stdin)
os.close(ready_read_fd) os.close(ready_read_fd)
self.terminal_ready_fd = ready_write_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 return pid
def mark_terminal_ready(self): def mark_terminal_ready(self):

View File

@@ -212,6 +212,14 @@ def wrap(text, limit=80):
return reversed(lines) return reversed(lines)
def get_defaults_from_seq(seq):
ans = {}
for opt in seq:
if not isinstance(opt, str):
ans[opt['dest']] = defval_for_opt(opt)
return ans
default_msg = ('''\ default_msg = ('''\
Run the :italic:`{appname}` terminal emulator. You can also specify the :italic:`program` 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`. to run inside :italic:`{appname}` as normal arguments following the :italic:`options`.
@@ -506,7 +514,7 @@ Detach from the controlling terminal, if any
--session --session
Path to a file containing the startup :italic:`session` (tabs, windows, layout, programs). 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 --hold
@@ -720,9 +728,11 @@ def create_opts(args, debug_config=False, accumulate_bad_lines=None):
import subprocess import subprocess
print(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip()) print(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip())
if os.path.exists('/etc/issue'): 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'): 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)) config = tuple(x for x in config if os.path.exists(x))
if config: if config:
print(green('Loaded config files:'), ', '.join(config)) print(green('Loaded config files:'), ', '.join(config))

View File

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

View File

@@ -7,7 +7,7 @@ import os
import sys import sys
from contextlib import suppress from contextlib import suppress
from .cli import parse_args from .cli import parse_args, parse_option_spec, get_defaults_from_seq
from .config import parse_config, parse_send_text_bytes from .config import parse_config, parse_send_text_bytes
from .constants import appname from .constants import appname
from .fast_data_types import focus_os_window from .fast_data_types import focus_os_window
@@ -36,7 +36,33 @@ class UnknownLayout(ValueError):
cmap = {} cmap = {}
def cmd(short_desc, desc=None, options_spec=None, no_response=False, argspec='...', string_return_is_error=False, args_count=None): def cmd(
short_desc,
desc=None,
options_spec=None,
no_response=False,
argspec='...',
string_return_is_error=False,
args_count=None,
):
if options_spec:
defaults = None
def get_defaut_value(name, missing=None):
nonlocal defaults
if defaults is None:
defaults = get_defaults_from_seq(parse_option_spec(options_spec)[0])
return defaults.get(name, missing)
else:
def get_defaut_value(name, missing=None):
return missing
def payload_get(payload, key, opt_name=None):
ans = payload.get(key, payload_get)
if ans is not payload_get:
return ans
return get_defaut_value(opt_name or key)
def w(func): def w(func):
func.short_desc = short_desc func.short_desc = short_desc
@@ -49,6 +75,8 @@ def cmd(short_desc, desc=None, options_spec=None, no_response=False, argspec='..
func.no_response = no_response func.no_response = no_response
func.string_return_is_error = string_return_is_error func.string_return_is_error = string_return_is_error
func.args_count = 0 if not argspec else args_count func.args_count = 0 if not argspec else args_count
func.get_default = get_defaut_value
func.payload_get = payload_get
cmap[func.name] = func cmap[func.name] = func
return func return func
return w return w
@@ -109,6 +137,9 @@ def windows_for_payload(boss, window, payload):
argspec='' argspec=''
) )
def cmd_ls(global_opts, opts, args): def cmd_ls(global_opts, opts, args):
'''
No payload
'''
pass pass
@@ -135,6 +166,11 @@ By default, the font size is only changed in the active OS window,
this option will cause it to be changed in all OS windows. this option will cause it to be changed in all OS windows.
''') ''')
def cmd_set_font_size(global_opts, opts, args): def cmd_set_font_size(global_opts, opts, args):
'''
size+: The new font size in pts (a positive number)
all: Boolean whether to change font size in the current window or all windows
increment_op: The string ``+`` or ``-`` to interpret size as an increment
'''
if not args: if not args:
raise SystemExit('No font size specified') raise SystemExit('No font size specified')
fs = args[0] fs = args[0]
@@ -143,7 +179,9 @@ def cmd_set_font_size(global_opts, opts, args):
def set_font_size(boss, window, payload): def set_font_size(boss, window, payload):
boss.change_font_size(payload['all'], payload['increment_op'], payload['size']) boss.change_font_size(
cmd_set_font_size.payload_get(payload, 'all'),
payload.get('increment_op', None), payload['size'])
# }}} # }}}
@@ -170,6 +208,12 @@ are sent as is, not interpreted for escapes.
argspec='[TEXT TO SEND]' argspec='[TEXT TO SEND]'
) )
def cmd_send_text(global_opts, opts, args): def cmd_send_text(global_opts, opts, args):
'''
text+: The text being sent
is_binary+: If False text is interpreted as a python string literal instead of plain text
match: A string indicating the window to send text to
match_tab: A string indicating the tab to send text to
'''
limit = 1024 limit = 1024
ret = {'match': opts.match, 'is_binary': False, 'match_tab': opts.match_tab} ret = {'match': opts.match, 'is_binary': False, 'match_tab': opts.match_tab}
@@ -235,12 +279,14 @@ def cmd_send_text(global_opts, opts, args):
def send_text(boss, window, payload): def send_text(boss, window, payload):
windows = [boss.active_window] windows = [boss.active_window]
match = payload['match'] pg = cmd_send_text.payload_get
match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if payload['match_tab']: mt = pg(payload, 'match_tab')
if mt:
windows = [] windows = []
tabs = tuple(boss.match_tabs(payload['match_tab'])) tabs = tuple(boss.match_tabs(mt))
if not tabs: if not tabs:
raise MatchError(payload['match_tab'], 'tabs') raise MatchError(payload['match_tab'], 'tabs')
for tab in tabs: for tab in tabs:
@@ -269,19 +315,25 @@ want to allow other programs to change it afterwards, use this option.
argspec='TITLE ...' argspec='TITLE ...'
) )
def cmd_set_window_title(global_opts, opts, args): def cmd_set_window_title(global_opts, opts, args):
'''
title+: The new title
match: Which windows to change the title in
temporary: Boolean indicating if the change is temporary or permanent
'''
return {'title': ' '.join(args), 'match': opts.match, 'temporary': opts.temporary} return {'title': ' '.join(args), 'match': opts.match, 'temporary': opts.temporary}
def set_window_title(boss, window, payload): def set_window_title(boss, window, payload):
windows = [window or boss.active_window] windows = [window or boss.active_window]
match = payload['match'] pg = cmd_set_window_title.payload_get
match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if not windows: if not windows:
raise MatchError(match) raise MatchError(match)
for window in windows: for window in windows:
if window: if window:
if payload['temporary']: if pg(payload, 'temporary'):
window.override_title = None window.override_title = None
window.title_changed(payload['title']) window.title_changed(payload['title'])
else: else:
@@ -301,11 +353,16 @@ def set_window_title(boss, window, payload):
argspec='TITLE ...' argspec='TITLE ...'
) )
def cmd_set_tab_title(global_opts, opts, args): def cmd_set_tab_title(global_opts, opts, args):
'''
title+: The new title
match: Which tab to change the title of
'''
return {'title': ' '.join(args), 'match': opts.match} return {'title': ' '.join(args), 'match': opts.match}
def set_tab_title(boss, window, payload): def set_tab_title(boss, window, payload):
match = payload['match'] pg = cmd_set_tab_title.payload_get
match = pg(payload, 'match')
if match: if match:
tabs = tuple(boss.match_tabs(match)) tabs = tuple(boss.match_tabs(match))
if not tabs: if not tabs:
@@ -327,6 +384,10 @@ def set_tab_title(boss, window, payload):
argspec='LAYOUT_NAME' argspec='LAYOUT_NAME'
) )
def cmd_goto_layout(global_opts, opts, args): def cmd_goto_layout(global_opts, opts, args):
'''
layout+: The new layout name
match: Which tab to change the layout of
'''
try: try:
return {'layout': args[0], 'match': opts.match} return {'layout': args[0], 'match': opts.match}
except IndexError: except IndexError:
@@ -334,7 +395,8 @@ def cmd_goto_layout(global_opts, opts, args):
def goto_layout(boss, window, payload): def goto_layout(boss, window, payload):
match = payload['match'] pg = cmd_goto_layout.payload_get
match = pg(payload, 'match')
if match: if match:
if match == 'all': if match == 'all':
tabs = tuple(boss.all_tabs) tabs = tuple(boss.all_tabs)
@@ -361,11 +423,15 @@ def goto_layout(boss, window, payload):
options_spec=MATCH_TAB_OPTION, options_spec=MATCH_TAB_OPTION,
) )
def cmd_last_used_layout(global_opts, opts, args): def cmd_last_used_layout(global_opts, opts, args):
'''
match: Which tab to change the layout of
'''
return {'match': opts.match} return {'match': opts.match}
def last_used_layout(boss, window, payload): def last_used_layout(boss, window, payload):
match = payload['match'] pg = cmd_last_used_layout.payload_get
match = pg(payload, 'match')
if match: if match:
if match == 'all': if match == 'all':
tabs = tuple(boss.all_tabs) tabs = tuple(boss.all_tabs)
@@ -392,17 +458,22 @@ If specified close the window this command is run in, rather than the active win
argspec='' argspec=''
) )
def cmd_close_window(global_opts, opts, args): def cmd_close_window(global_opts, opts, args):
'''
match: Which window to close
self: Boolean indicating whether to close the window the command is run in
'''
return {'match': opts.match, 'self': opts.self} return {'match': opts.match, 'self': opts.self}
def close_window(boss, window, payload): def close_window(boss, window, payload):
match = payload['match'] pg = cmd_close_window.payload_get
match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if not windows: if not windows:
raise MatchError(match) raise MatchError(match)
else: else:
windows = [window if window and payload['self'] else boss.active_window] windows = [window if window and pg(payload, 'self') else boss.active_window]
for window in windows: for window in windows:
if window: if window:
boss.close_window(window) boss.close_window(window)
@@ -437,22 +508,29 @@ If specified resize the window this command is run in, rather than the active wi
string_return_is_error=True string_return_is_error=True
) )
def cmd_resize_window(global_opts, opts, args): def cmd_resize_window(global_opts, opts, args):
'''
match: Which window to resize
self: Boolean indicating whether to close the window the command is run in
increment: Integer specifying the resize increment
axis: One of :code:`horizontal, vertical` or :code:`reset`
'''
return {'match': opts.match, 'increment': opts.increment, 'axis': opts.axis, 'self': opts.self} return {'match': opts.match, 'increment': opts.increment, 'axis': opts.axis, 'self': opts.self}
def resize_window(boss, window, payload): def resize_window(boss, window, payload):
match = payload['match'] pg = cmd_resize_window.payload_get
match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if not windows: if not windows:
raise MatchError(match) raise MatchError(match)
else: else:
windows = [window if window and payload['self'] else boss.active_window] windows = [window if window and pg(payload, 'self') else boss.active_window]
resized = False resized = False
if windows and windows[0]: if windows and windows[0]:
resized = boss.resize_layout_window( resized = boss.resize_layout_window(
windows[0], increment=payload['increment'], is_horizontal=payload['axis'] == 'horizontal', windows[0], increment=pg(payload, 'increment'), is_horizontal=pg(payload, 'axis') == 'horizontal',
reset=payload['axis'] == 'reset' reset=pg(payload, 'axis') == 'reset'
) )
return resized return resized
# }}} # }}}
@@ -469,17 +547,22 @@ If specified close the tab this command is run in, rather than the active tab.
argspec='' argspec=''
) )
def cmd_close_tab(global_opts, opts, args): def cmd_close_tab(global_opts, opts, args):
'''
match: Which tab to close
self: Boolean indicating whether to close the window the command is run in
'''
return {'match': opts.match, 'self': opts.self} return {'match': opts.match, 'self': opts.self}
def close_tab(boss, window, payload): def close_tab(boss, window, payload):
match = payload['match'] pg = cmd_close_tab.payload_get
match = pg(payload, 'match')
if match: if match:
tabs = tuple(boss.match_tabs(match)) tabs = tuple(boss.match_tabs(match))
if not tabs: if not tabs:
raise MatchError(match, 'tabs') raise MatchError(match, 'tabs')
else: else:
tabs = [boss.tab_for_window(window) if window and payload['self'] else boss.active_tab] tabs = [boss.tab_for_window(window) if window and pg(payload, 'self') else boss.active_tab]
for tab in tabs: for tab in tabs:
if window: if window:
if tab: if tab:
@@ -537,6 +620,15 @@ the id of the new window will not be printed out.
argspec='[CMD ...]' argspec='[CMD ...]'
) )
def cmd_new_window(global_opts, opts, args): def cmd_new_window(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
title: Title for the new window
cwd: Working directory for the new window
tab_title: Title for the new tab
window_type: One of :code:`kitty` or :code:`os`
keep_focus: Boolean indicating whether the current window should retain focus or not
'''
if opts.no_response: if opts.no_response:
global_opts.no_command_response = True global_opts.no_command_response = True
return {'match': opts.match, 'title': opts.title, 'cwd': opts.cwd, return {'match': opts.match, 'title': opts.title, 'cwd': opts.cwd,
@@ -546,28 +638,29 @@ def cmd_new_window(global_opts, opts, args):
def new_window(boss, window, payload): def new_window(boss, window, payload):
w = SpecialWindow(cmd=payload['args'] or None, override_title=payload['title'], cwd=payload['cwd']) pg = cmd_new_window.payload_get
w = SpecialWindow(cmd=payload['args'] or None, override_title=pg(payload, 'title'), cwd=pg(payload, 'cwd'))
old_window = boss.active_window old_window = boss.active_window
if payload['new_tab']: if pg(payload, 'new_tab'):
boss._new_tab(w) boss._new_tab(w)
tab = boss.active_tab tab = boss.active_tab
if payload['tab_title']: if pg(payload, 'tab_title'):
tab.set_title(payload['tab_title']) tab.set_title(pg(payload, 'tab_title'))
wid = boss.active_window.id wid = boss.active_window.id
if payload['keep_focus'] and old_window: if pg(payload, 'keep_focus') and old_window:
boss.set_active_window(old_window) boss.set_active_window(old_window)
return None if payload['no_response'] else str(wid) return None if pg(payload, 'no_response') else str(wid)
if payload['window_type'] == 'os': if pg(payload, 'window_type') == 'os':
boss._new_os_window(w) boss._new_os_window(w)
wid = boss.active_window.id wid = boss.active_window.id
if payload['keep_focus'] and old_window: if pg(payload, 'keep_focus') and old_window:
os_window_id = boss.set_active_window(old_window) os_window_id = boss.set_active_window(old_window)
if os_window_id: if os_window_id:
focus_os_window(os_window_id) focus_os_window(os_window_id)
return None if payload['no_response'] else str(wid) return None if pg(payload, 'no_response') else str(wid)
match = payload['match'] match = pg(payload, 'match')
if match: if match:
tabs = tuple(boss.match_tabs(match)) tabs = tuple(boss.match_tabs(match))
if not tabs: if not tabs:
@@ -576,9 +669,9 @@ def new_window(boss, window, payload):
tabs = [boss.active_tab] tabs = [boss.active_tab]
tab = tabs[0] tab = tabs[0]
w = tab.new_special_window(w) w = tab.new_special_window(w)
if payload['keep_focus'] and old_window: if pg(payload, 'keep_focus') and old_window:
boss.set_active_window(old_window) boss.set_active_window(old_window)
return None if payload['no_response'] else str(w.id) return None if pg(payload, 'no_response') else str(w.id)
# }}} # }}}
@@ -596,14 +689,18 @@ the command will exit with a success code.
''' '''
) )
def cmd_focus_window(global_opts, opts, args): def cmd_focus_window(global_opts, opts, args):
'''
match: The window to focus
'''
if opts.no_response: if opts.no_response:
global_opts.no_command_response = True global_opts.no_command_response = True
return {'match': opts.match, 'no_response': opts.no_response} return {'match': opts.match, 'no_response': opts.no_response}
def focus_window(boss, window, payload): def focus_window(boss, window, payload):
pg = cmd_focus_window.payload_get
windows = [window or boss.active_window] windows = [window or boss.active_window]
match = payload['match'] match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if not windows: if not windows:
@@ -617,6 +714,59 @@ def focus_window(boss, window, payload):
# }}} # }}}
# scroll_window {{{
@cmd(
'Scroll the specified window',
'Scroll the specified window, if no window is specified, scroll the window this command is run inside.'
' SCROLL_AMOUNT can be either the keywords :code:`start` or :code:`end` or an'
' argument of the form <number>[unit][+-]. For example, 30 will scroll down 30 lines and 2p- will'
' scroll up 2 pages.',
argspec='SCROLL_AMOUNT',
options_spec=MATCH_WINDOW_OPTION
)
def cmd_scroll_window(global_opts, opts, args):
'''
amount+: The amount to scroll, a two item list with the first item being \
either a number or the keywords, start and end. \
And the second item being either 'p' for pages or 'l' for lines.
match: The window to scroll
'''
amt = args[0]
ans = {'match': opts.match}
if amt in ('start', 'end'):
ans['amount'] = amt, None
else:
pages = 'p' in amt
amt = amt.replace('p', '')
mult = -1 if amt.endswith('-') else 1
amt = int(amt.replace('-', ''))
ans['amount'] = [amt * mult, 'p' if pages else 'l']
return ans
def scroll_window(boss, window, payload):
pg = cmd_scroll_window.payload_get
windows = [window or boss.active_window]
match = pg(payload, 'match')
amt = pg(payload, 'amount')
if match:
windows = tuple(boss.match_windows(match))
if not windows:
raise MatchError(match)
for window in windows:
if window:
if amt[0] in ('start', 'end'):
getattr(window, {'start': 'scroll_home'}.get(amt[0], 'scroll_end'))()
else:
amt, unit = amt
unit = 'page' if unit == 'p' else 'line'
direction = 'up' if amt < 0 else 'down'
func = getattr(window, 'scroll_{}_{}'.format(unit, direction))
for i in range(abs(amt)):
func()
# }}}
# focus_tab {{{ # focus_tab {{{
@cmd( @cmd(
'Focus the specified tab', 'Focus the specified tab',
@@ -630,16 +780,19 @@ Don't wait for a response indicating the success of the action. Note that
using this option means that you will not be notified of failures. using this option means that you will not be notified of failures.
''', ''',
argspec='', argspec='',
no_response=True,
) )
def cmd_focus_tab(global_opts, opts, args): def cmd_focus_tab(global_opts, opts, args):
'''
match: The tab to focus
'''
if opts.no_response: if opts.no_response:
global_opts.no_command_response = True global_opts.no_command_response = True
return {'match': opts.match} return {'match': opts.match}
def focus_tab(boss, window, payload): def focus_tab(boss, window, payload):
match = payload['match'] pg = cmd_focus_tab.payload_get
match = pg(payload, 'match')
tabs = tuple(boss.match_tabs(match)) tabs = tuple(boss.match_tabs(match))
if not tabs: if not tabs:
raise MatchError(match, 'tabs') raise MatchError(match, 'tabs')
@@ -673,22 +826,29 @@ If specified get text from the window this command is run in, rather than the ac
argspec='' argspec=''
) )
def cmd_get_text(global_opts, opts, args): def cmd_get_text(global_opts, opts, args):
'''
match: The tab to focus
extent: One of :code:`screen`, :code:`all`, or :code:`selection`
ansi: Boolean, if True send ANSI formatting codes
self: Boolean, if True use window command was run in
'''
return {'match': opts.match, 'extent': opts.extent, 'ansi': opts.ansi, 'self': opts.self} return {'match': opts.match, 'extent': opts.extent, 'ansi': opts.ansi, 'self': opts.self}
def get_text(boss, window, payload): def get_text(boss, window, payload):
match = payload['match'] pg = cmd_get_text.payload_get
match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if not windows: if not windows:
raise MatchError(match) raise MatchError(match)
else: else:
windows = [window if window and payload['self'] else boss.active_window] windows = [window if window and pg(payload, 'self') else boss.active_window]
window = windows[0] window = windows[0]
if payload['extent'] == 'selection': if pg(payload, 'extent') == 'selection':
ans = window.text_for_selection() ans = window.text_for_selection()
else: else:
ans = window.as_text(as_ansi=bool(payload['ansi']), add_history=payload['extent'] == 'all') ans = window.as_text(as_ansi=bool(pg(payload, 'ansi')), add_history=pg(payload, 'extent') == 'all')
return ans return ans
# }}} # }}}
@@ -720,6 +880,15 @@ this option, any color arguments are ignored and --configured and --all are impl
argspec='COLOR_OR_FILE ...' argspec='COLOR_OR_FILE ...'
) )
def cmd_set_colors(global_opts, opts, args): 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
match_window: Window to change colors in
match_tab: Tab to change colors in
all: Boolean indicating change colors everywhere or not
configured: Boolean indicating whether to change the configured colors. Must be True if reset is True
reset: Boolean indicating colors should be reset to startup values
'''
from .rgb import color_as_int, Color from .rgb import color_as_int, Color
colors, cursor_text_color = {}, False colors, cursor_text_color = {}, False
if not opts.reset: if not opts.reset:
@@ -732,16 +901,17 @@ def cmd_set_colors(global_opts, opts, args):
cursor_text_color = colors.pop('cursor_text_color', False) cursor_text_color = colors.pop('cursor_text_color', False)
colors = {k: color_as_int(v) for k, v in colors.items() if isinstance(v, Color)} colors = {k: color_as_int(v) for k, v in colors.items() if isinstance(v, Color)}
return { return {
'title': ' '.join(args), 'match_window': opts.match, 'match_tab': opts.match_tab, 'match_window': opts.match, 'match_tab': opts.match_tab,
'all': opts.all or opts.reset, 'configured': opts.configured or opts.reset, 'all': opts.all or opts.reset, 'configured': opts.configured or opts.reset,
'colors': colors, 'reset': opts.reset, 'cursor_text_color': cursor_text_color 'colors': colors, 'reset': opts.reset, 'cursor_text_color': cursor_text_color
} }
def set_colors(boss, window, payload): def set_colors(boss, window, payload):
pg = cmd_set_colors.payload_get
from .rgb import color_as_int, Color from .rgb import color_as_int, Color
windows = windows_for_payload(boss, window, payload) windows = windows_for_payload(boss, window, payload)
if payload['reset']: if pg(payload, 'reset'):
payload['colors'] = {k: color_as_int(v) for k, v in boss.startup_colors.items()} payload['colors'] = {k: color_as_int(v) for k, v in boss.startup_colors.items()}
payload['cursor_text_color'] = boss.startup_cursor_text_color payload['cursor_text_color'] = boss.startup_cursor_text_color
profiles = tuple(w.screen.color_profile for w in windows) profiles = tuple(w.screen.color_profile for w in windows)
@@ -749,8 +919,8 @@ def set_colors(boss, window, payload):
cursor_text_color = payload.get('cursor_text_color', False) cursor_text_color = payload.get('cursor_text_color', False)
if isinstance(cursor_text_color, (tuple, list, Color)): if isinstance(cursor_text_color, (tuple, list, Color)):
cursor_text_color = color_as_int(Color(*cursor_text_color)) cursor_text_color = color_as_int(Color(*cursor_text_color))
patch_color_profiles(payload['colors'], cursor_text_color, profiles, payload['configured']) patch_color_profiles(payload['colors'], cursor_text_color, profiles, pg(payload, 'configured'))
boss.patch_colors(payload['colors'], cursor_text_color, payload['configured']) boss.patch_colors(payload['colors'], cursor_text_color, pg(payload, 'configured'))
default_bg_changed = 'background' in payload['colors'] default_bg_changed = 'background' in payload['colors']
for w in windows: for w in windows:
if default_bg_changed: if default_bg_changed:
@@ -772,18 +942,23 @@ configured colors.
''' + '\n\n' + MATCH_WINDOW_OPTION ''' + '\n\n' + MATCH_WINDOW_OPTION
) )
def cmd_get_colors(global_opts, opts, args): def cmd_get_colors(global_opts, opts, args):
'''
match: The window to get the colors for
configured: Boolean indicating whether to get configured or current colors
'''
return {'configured': opts.configured, 'match': opts.match} return {'configured': opts.configured, 'match': opts.match}
def get_colors(boss, window, payload): def get_colors(boss, window, payload):
from .rgb import Color, color_as_sharp, color_from_int from .rgb import Color, color_as_sharp, color_from_int
pg = cmd_get_colors.payload_get
ans = {k: getattr(boss.opts, k) for k in boss.opts if isinstance(getattr(boss.opts, k), Color)} ans = {k: getattr(boss.opts, k) for k in boss.opts if isinstance(getattr(boss.opts, k), Color)}
if not payload['configured']: if not pg(payload, 'configured'):
windows = (window or boss.active_window,) windows = (window or boss.active_window,)
if payload['match']: if pg(payload, 'match'):
windows = tuple(boss.match_windows(payload['match'])) windows = tuple(boss.match_windows(pg(payload, 'match')))
if not windows: if not windows:
raise MatchError(payload['match']) raise MatchError(pg(payload, 'match'))
ans.update({k: color_from_int(v) for k, v in windows[0].current_colors.items()}) ans.update({k: color_from_int(v) for k, v in windows[0].current_colors.items()})
all_keys = natsort_ints(ans) all_keys = natsort_ints(ans)
maxlen = max(map(len, all_keys)) maxlen = max(map(len, all_keys))
@@ -808,24 +983,23 @@ cause colors to be changed in all windows.
args_count=1 args_count=1
) )
def cmd_set_background_opacity(global_opts, opts, args): def cmd_set_background_opacity(global_opts, opts, args):
'''
opacity+: A number between 0.1 and 1
match_window: Window to change opacity in
match_tab: Tab to change opacity in
all: Boolean indicating operate on all windows
'''
opacity = max(0.1, min(float(args[0]), 1.0)) opacity = max(0.1, min(float(args[0]), 1.0))
return { return {
'opacity': opacity, 'match_window': opts.match, 'opacity': opacity, 'match_window': opts.match,
'all': opts.all, 'all': opts.all, 'match_tab': opts.match_tab
} }
def set_background_opacity(boss, window, payload): def set_background_opacity(boss, window, payload):
if not boss.opts.dynamic_background_opacity: 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') raise OpacityError('You must turn on the dynamic_background_opacity option in kitty.conf to be able to set background opacity')
if payload['all']: windows = windows_for_payload(boss, window, payload)
windows = tuple(boss.all_windows)
else:
windows = (window or boss.active_window,)
if payload['match_window']:
windows = tuple(boss.match_windows(payload['match_window']))
if not windows:
raise MatchError(payload['match_window'])
for os_window_id in {w.os_window_id for w in windows}: for os_window_id in {w.os_window_id for w in windows}:
boss._set_os_window_background_opacity(os_window_id, payload['opacity']) boss._set_os_window_background_opacity(os_window_id, payload['opacity'])
# }}} # }}}
@@ -846,6 +1020,12 @@ cause ligatures to be changed in all windows.
argspec='STRATEGY' argspec='STRATEGY'
) )
def cmd_disable_ligatures(global_opts, opts, args): def cmd_disable_ligatures(global_opts, opts, args):
'''
strategy+: One of :code:`never`, :code:`always` or :code:`cursor`
match_window: Window to change opacity in
match_tab: Tab to change opacity in
all: Boolean indicating operate on all windows
'''
strategy = args[0] strategy = args[0]
if strategy not in ('never', 'always', 'cursor'): if strategy not in ('never', 'always', 'cursor'):
raise ValueError('{} is not a valid disable_ligatures strategy'.format('strategy')) raise ValueError('{} is not a valid disable_ligatures strategy'.format('strategy'))
@@ -872,6 +1052,11 @@ def disable_ligatures(boss, window, payload):
argspec='kitten_name', argspec='kitten_name',
) )
def cmd_kitten(global_opts, opts, args): def cmd_kitten(global_opts, opts, args):
'''
kitten+: The name of the kitten to run
args: Arguments to pass to the kitten as a list
match: The window to run the kitten over
'''
if len(args) < 1: if len(args) < 1:
raise SystemExit('Must specify kitten name') raise SystemExit('Must specify kitten name')
return {'match': opts.match, 'args': list(args)[1:], 'kitten': args[0]} return {'match': opts.match, 'args': list(args)[1:], 'kitten': args[0]}
@@ -879,14 +1064,15 @@ def cmd_kitten(global_opts, opts, args):
def kitten(boss, window, payload): def kitten(boss, window, payload):
windows = [window or boss.active_window] windows = [window or boss.active_window]
match = payload['match'] pg = cmd_kitten.payload_get
match = pg(payload, 'match')
if match: if match:
windows = tuple(boss.match_windows(match)) windows = tuple(boss.match_windows(match))
if not windows: if not windows:
raise MatchError(match) raise MatchError(match)
for window in windows: for window in windows:
if window: if window:
boss._run_kitten(payload['kitten'], args=tuple(payload['args']), window=window) boss._run_kitten(payload['kitten'], args=tuple(payload.get('args', ())), window=window)
break break
# }}} # }}}

View File

@@ -49,7 +49,7 @@ find_app_name(void) {
for (i = 0; i < sizeof(name_keys) / sizeof(name_keys[0]); i++) for (i = 0; i < sizeof(name_keys) / sizeof(name_keys[0]); i++)
{ {
id name = [infoDictionary objectForKey:name_keys[i]]; id name = infoDictionary[name_keys[i]];
if (name && if (name &&
[name isKindOfClass:[NSString class]] && [name isKindOfClass:[NSString class]] &&
![name isEqualToString:@""]) ![name isEqualToString:@""])
@@ -60,7 +60,7 @@ find_app_name(void) {
char** progname = _NSGetProgname(); char** progname = _NSGetProgname();
if (progname && *progname) if (progname && *progname)
return [NSString stringWithUTF8String:*progname]; return @(*progname);
// Really shouldn't get here // Really shouldn't get here
return @"kitty"; return @"kitty";
@@ -132,7 +132,6 @@ set_notification_activated_callback(PyObject *self UNUSED, PyObject *callback) {
notification_activated_callback = callback; notification_activated_callback = callback;
Py_INCREF(callback); Py_INCREF(callback);
Py_RETURN_NONE; Py_RETURN_NONE;
} }
@interface NotificationDelegate : NSObject <NSUserNotificationCenterDelegate> @interface NotificationDelegate : NSObject <NSUserNotificationCenterDelegate>
@@ -172,7 +171,7 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
NSUserNotification *n = [NSUserNotification new]; NSUserNotification *n = [NSUserNotification new];
NSImage *img = nil; NSImage *img = nil;
if (path_to_image) { if (path_to_image) {
NSString *p = [NSString stringWithUTF8String:path_to_image]; NSString *p = @(path_to_image);
NSURL *url = [NSURL fileURLWithPath:p]; NSURL *url = [NSURL fileURLWithPath:p];
img = [[NSImage alloc] initWithContentsOfURL:url]; img = [[NSImage alloc] initWithContentsOfURL:url];
[url release]; [p release]; [url release]; [p release];
@@ -184,14 +183,14 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
} }
#define SET(x) { \ #define SET(x) { \
if (x) { \ if (x) { \
NSString *t = [NSString stringWithUTF8String:x]; \ NSString *t = @(x); \
n.x = t; \ n.x = t; \
[t release]; \ [t release]; \
}} }}
SET(title); SET(subtitle); SET(informativeText); SET(title); SET(subtitle); SET(informativeText);
#undef SET #undef SET
if (identifier) { if (identifier) {
n.userInfo = @{@"user_id": [NSString stringWithUTF8String:identifier]}; n.userInfo = @{@"user_id": @(identifier)};
} }
[center deliverNotification:n]; [center deliverNotification:n];
Py_RETURN_NONE; Py_RETURN_NONE;
@@ -233,6 +232,7 @@ cocoa_send_notification(PyObject *self UNUSED, PyObject *args) {
void void
cocoa_create_global_menu(void) { cocoa_create_global_menu(void) {
@autoreleasepool { @autoreleasepool {
NSString* app_name = find_app_name(); NSString* app_name = find_app_name();
NSMenu* bar = [[NSMenu alloc] init]; NSMenu* bar = [[NSMenu alloc] init];
GlobalMenuTarget *global_menu_target = [GlobalMenuTarget shared_instance]; GlobalMenuTarget *global_menu_target = [GlobalMenuTarget shared_instance];
@@ -324,11 +324,12 @@ cocoa_create_global_menu(void) {
[NSApp setServicesProvider:[[[ServiceProvider alloc] init] autorelease]]; [NSApp setServicesProvider:[[[ServiceProvider alloc] init] autorelease]];
}
} // autoreleasepool
} }
void void
cocoa_update_title(PyObject *pytitle) { cocoa_update_menu_bar_title(PyObject *pytitle) {
NSString *title = [[NSString alloc] initWithUTF8String:PyUnicode_AsUTF8(pytitle)]; NSString *title = [[NSString alloc] initWithUTF8String:PyUnicode_AsUTF8(pytitle)];
NSMenu *bar = [NSApp mainMenu]; NSMenu *bar = [NSApp mainMenu];
if (title_menu != NULL) { if (title_menu != NULL) {
@@ -395,6 +396,7 @@ cocoa_get_workspace_ids(void *w, size_t *workspace_ids, size_t array_sz) {
static PyObject* static PyObject*
cocoa_get_lang(PyObject UNUSED *self) { cocoa_get_lang(PyObject UNUSED *self) {
@autoreleasepool { @autoreleasepool {
NSString* locale = nil; NSString* locale = nil;
NSString* lang_code = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode]; NSString* lang_code = [[NSLocale currentLocale] objectForKey:NSLocaleLanguageCode];
NSString* country_code = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode]; NSString* country_code = [[NSLocale currentLocale] objectForKey:NSLocaleCountryCode];
@@ -405,12 +407,14 @@ cocoa_get_lang(PyObject UNUSED *self) {
} }
if (!locale) { Py_RETURN_NONE; } if (!locale) { Py_RETURN_NONE; }
return Py_BuildValue("s", [locale UTF8String]); return Py_BuildValue("s", [locale UTF8String]);
}
} // autoreleasepool
} }
double double
cocoa_cursor_blink_interval(void) { cocoa_cursor_blink_interval(void) {
@autoreleasepool { @autoreleasepool {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
double on_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOn"]; double on_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOn"];
double off_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOff"]; double off_period_ms = [defaults doubleForKey:@"NSTextInsertionPointBlinkPeriodOff"];
@@ -422,19 +426,21 @@ cocoa_cursor_blink_interval(void) {
ans = period_ms; ans = period_ms;
} }
return ans > max_value ? 0.0 : ans; return ans > max_value ? 0.0 : ans;
}
} // autoreleasepool
} }
void void
cocoa_set_hide_from_tasks(void) { cocoa_set_activation_policy(bool hide_from_tasks) {
[NSApp setActivationPolicy:NSApplicationActivationPolicyAccessory]; [NSApp setActivationPolicy:(hide_from_tasks ? NSApplicationActivationPolicyAccessory : NSApplicationActivationPolicyRegular)];
} }
void void
cocoa_set_titlebar_color(void *w, color_type titlebar_color) cocoa_set_titlebar_color(void *w, color_type titlebar_color)
{ {
@autoreleasepool { @autoreleasepool {
NSWindow *window = (NSWindow *)w;
NSWindow *window = (NSWindow*)w;
double red = ((titlebar_color >> 16) & 0xFF) / 255.0; double red = ((titlebar_color >> 16) & 0xFF) / 255.0;
double green = ((titlebar_color >> 8) & 0xFF) / 255.0; double green = ((titlebar_color >> 8) & 0xFF) / 255.0;
@@ -455,17 +461,31 @@ cocoa_set_titlebar_color(void *w, color_type titlebar_color)
} else { } else {
[window setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantLight]]; [window setAppearance:[NSAppearance appearanceNamed:NSAppearanceNameVibrantLight]];
} }
}
} // autoreleasepool
} }
static void static void
cleanup() { cleanup() {
@autoreleasepool { @autoreleasepool {
if (dockMenu) [dockMenu release]; if (dockMenu) [dockMenu release];
dockMenu = nil; dockMenu = nil;
if (notification_activated_callback) Py_DECREF(notification_activated_callback); if (notification_activated_callback) Py_DECREF(notification_activated_callback);
notification_activated_callback = NULL; notification_activated_callback = NULL;
}
} // autoreleasepool
}
void
cocoa_hide_window_title(void *w)
{
@autoreleasepool {
NSWindow *window = (NSWindow*)w;
[window setTitleVisibility:NSWindowTitleHidden];
} // autoreleasepool
} }
static PyMethodDef module_methods[] = { static PyMethodDef module_methods[] = {

View File

@@ -36,12 +36,12 @@ init_FG_BG_table(void) {
// colors 16..232: the 6x6x6 color cube // colors 16..232: the 6x6x6 color cube
const uint8_t valuerange[6] = {0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff}; const uint8_t valuerange[6] = {0x00, 0x5f, 0x87, 0xaf, 0xd7, 0xff};
uint8_t i, j=16; uint8_t i, j=16;
for(i = 0; i < 217; i++, j++) { for(i = 0; i < 216; i++, j++) {
uint8_t r = valuerange[(i / 36) % 6], g = valuerange[(i / 6) % 6], b = valuerange[i % 6]; uint8_t r = valuerange[(i / 36) % 6], g = valuerange[(i / 6) % 6], b = valuerange[i % 6];
FG_BG_256[j] = (r << 16) | (g << 8) | b; FG_BG_256[j] = (r << 16) | (g << 8) | b;
} }
// colors 233..255: grayscale // colors 232..255: grayscale
for(i = 1; i < 24; i++, j++) { for(i = 0; i < 24; i++, j++) {
uint8_t v = 8 + i * 10; uint8_t v = 8 + i * 10;
FG_BG_256[j] = (v << 16) | (v << 8) | v; FG_BG_256[j] = (v << 16) | (v << 8) | v;
} }
@@ -98,6 +98,15 @@ update_ansi_color_table(ColorProfile *self, PyObject *val) {
Py_RETURN_NONE; Py_RETURN_NONE;
} }
void
copy_color_profile(ColorProfile *dest, ColorProfile *src) {
memcpy(dest->color_table, src->color_table, sizeof(dest->color_table));
memcpy(dest->orig_color_table, src->orig_color_table, sizeof(dest->color_table));
memcpy(&dest->configured, &src->configured, sizeof(dest->configured));
memcpy(&dest->overridden, &src->overridden, sizeof(dest->overridden));
dest->dirty = true;
}
static PyObject* static PyObject*
patch_color_profiles(PyObject *module UNUSED, PyObject *args) { patch_color_profiles(PyObject *module UNUSED, PyObject *args) {
PyObject *spec, *profiles, *v; ColorProfile *self; int change_configured; PyObject *cursor_text_color; PyObject *spec, *profiles, *v; ColorProfile *self; int change_configured; PyObject *cursor_text_color;
@@ -272,7 +281,7 @@ set_configured_colors(ColorProfile *self, PyObject *args) {
void void
copy_color_table_to_buffer(ColorProfile *self, color_type *buf, int offset, size_t stride) { copy_color_table_to_buffer(ColorProfile *self, color_type *buf, int offset, size_t stride) {
size_t i; size_t i;
stride = MAX(1, stride); stride = MAX(1u, stride);
for (i = 0, buf = buf + offset; i < sizeof(self->color_table)/sizeof(self->color_table[0]); i++, buf += stride) { for (i = 0, buf = buf + offset; i < sizeof(self->color_table)/sizeof(self->color_table[0]); i++, buf += stride) {
*buf = self->color_table[i]; *buf = self->color_table[i];
} }

View File

@@ -12,6 +12,25 @@ from .cli import options_for_completion, parse_option_spec
from .cmds import cmap from .cmds import cmap
from .shell import options_for_cmd from .shell import options_for_cmd
'''
To add completion for a new shell, you need to:
1) Add an entry to completion scripts for your shell, this is
a simple function that call's kitty's completion code and passes the
results to the shell's completion system. This can be output by
`kitty +complete setup shell_name` and its output goes into
your shell's rc file.
2) Add an input_parser function, this takes the input from
the shell for the text being completed and returns a list of words
alongwith a boolean indicating if we are on a new word or not. This
is passed to kitty's completion system.
3) An output_serializer function that is responsible for
taking the results from kitty's completion system and converting
them into something your shell will understand.
'''
parsers, serializers = {}, {} parsers, serializers = {}, {}
@@ -131,7 +150,6 @@ def bash_output_serializer(ans):
lines.append('COMPREPLY+=({})'.format(shlex.quote(word))) lines.append('COMPREPLY+=({})'.format(shlex.quote(word)))
# debug('\n'.join(lines)) # debug('\n'.join(lines))
return '\n'.join(lines) return '\n'.join(lines)
# }}}
@output_serializer @output_serializer
@@ -142,6 +160,7 @@ def fish_output_serializer(ans):
lines.append(shlex.quote(word)) lines.append(shlex.quote(word))
# debug('\n'.join(lines)) # debug('\n'.join(lines))
return '\n'.join(lines) return '\n'.join(lines)
# }}}
def completions_for_first_word(ans, prefix, entry_points, namespaced_entry_points): def completions_for_first_word(ans, prefix, entry_points, namespaced_entry_points):
@@ -166,11 +185,37 @@ def kitty_cli_opts(ans, prefix=None):
def complete_kitty_cli_arg(ans, opt, prefix): def complete_kitty_cli_arg(ans, opt, prefix):
prefix = prefix or '' prefix = prefix or ''
if opt and opt['dest'] == 'override': if not opt:
return
dest = opt['dest']
if dest == 'override':
from kitty.config import option_names_for_completion from kitty.config import option_names_for_completion
k = 'Config directives' k = 'Config directives'
ans.match_groups[k] = {k+'=': None for k in option_names_for_completion() if k.startswith(prefix)} ans.match_groups[k] = {k+'=': None for k in option_names_for_completion() if k.startswith(prefix)}
ans.no_space_groups.add(k) ans.no_space_groups.add(k)
elif dest == 'config':
def is_conf_file(x):
if os.path.isdir(x):
return True
return x.lower().endswith('.conf')
complete_files_and_dirs(ans, prefix, files_group_name='Config files', predicate=is_conf_file)
elif dest == 'session':
complete_files_and_dirs(ans, prefix, files_group_name='Session files')
elif dest == 'directory':
complete_files_and_dirs(ans, prefix, files_group_name='Directories', predicate=os.path.isdir)
elif dest == 'start_as':
k = 'Start as'
ans.match_groups[k] = {x: x for x in 'normal,fullscreen,maximized,minimized'.split(',') if x.startswith(prefix)}
ans.no_space_groups.add(k)
elif dest == 'listen_on':
if ':' not in prefix:
k = 'Address type'
ans.match_groups[k] = {x: x for x in ('unix:', 'tcp:') if x.startswith(prefix)}
ans.no_space_groups.add(k)
elif prefix.startswith('unix:') and not prefix.startswith('@'):
complete_files_and_dirs(ans, prefix[len('unix:'):], files_group_name='UNIX sockets', add_prefix='unix:')
def complete_alias_map(ans, words, new_word, option_map, complete_args=None): def complete_alias_map(ans, words, new_word, option_map, complete_args=None):
@@ -254,9 +299,12 @@ def path_completion(prefix=''):
return dirs, files return dirs, files
def complete_files_and_dirs(ans, prefix, files_group_name='Files', predicate=None): def complete_files_and_dirs(ans, prefix, files_group_name='Files', predicate=None, add_prefix=None):
dirs, files = path_completion(prefix or '') dirs, files = path_completion(prefix or '')
files = filter(predicate, files) files = filter(predicate, files)
if add_prefix:
dirs = (add_prefix + x for x in dirs)
files = (add_prefix + x for x in files)
if dirs: if dirs:
ans.match_groups['Directories'] = dict.fromkeys(dirs) ans.match_groups['Directories'] = dict.fromkeys(dirs)

View File

@@ -177,12 +177,11 @@ def load_config(Options, defaults, parse_config, merge_configs, *paths, override
if not path: if not path:
continue continue
try: try:
f = open(path, encoding='utf-8', errors='replace') with open(path, encoding='utf-8', errors='replace') as f:
vals = parse_config(f)
except FileNotFoundError: except FileNotFoundError:
continue continue
with f: ans = merge_configs(ans, vals)
vals = parse_config(f)
ans = merge_configs(ans, vals)
if overrides is not None: if overrides is not None:
vals = parse_config(overrides) vals = parse_config(overrides)
ans = merge_configs(ans, vals) ans = merge_configs(ans, vals)

View File

@@ -20,21 +20,7 @@ from .conf.utils import (
from .config_data import all_options, parse_mods, type_map from .config_data import all_options, parse_mods, type_map
from .constants import cache_dir, defconf, is_macos from .constants import cache_dir, defconf, is_macos
from .utils import log_error from .utils import log_error
from .key_names import get_key_name_lookup from .key_names import get_key_name_lookup, key_name_aliases
named_keys = {
"'": 'APOSTROPHE',
',': 'COMMA',
'-': 'MINUS',
'_': 'UNDERSCORE',
'.': 'PERIOD',
'/': 'SLASH',
';': 'SEMICOLON',
'=': 'EQUAL',
'[': 'LEFT_BRACKET',
']': 'RIGHT_BRACKET',
'`': 'GRAVE_ACCENT'
}
def parse_shortcut(sc): def parse_shortcut(sc):
@@ -45,7 +31,7 @@ def parse_shortcut(sc):
if mods is None: if mods is None:
return None, None, None return None, None, None
key = parts[-1].upper() key = parts[-1].upper()
key = getattr(defines, 'GLFW_KEY_' + named_keys.get(key, key), None) key = getattr(defines, 'GLFW_KEY_' + key_name_aliases.get(key, key), None)
is_native = False is_native = False
if key is None: if key is None:
q = parts[-1] q = parts[-1]
@@ -263,6 +249,21 @@ class KeyDefinition:
self.trigger = defines.resolve_key_mods(kitty_mod, self.trigger[0]), self.trigger[1], self.trigger[2] self.trigger = defines.resolve_key_mods(kitty_mod, self.trigger[0]), self.trigger[1], self.trigger[2]
self.rest = tuple((defines.resolve_key_mods(kitty_mod, mods), is_native, key) for mods, is_native, key in self.rest) self.rest = tuple((defines.resolve_key_mods(kitty_mod, mods), is_native, key) for mods, is_native, key in self.rest)
def resolve_kitten_aliases(self, aliases):
if not self.action.args:
return
kitten = self.action.args[0]
rest = self.action.args[1] if len(self.action.args) > 1 else ''
changed = False
for key, expanded in aliases.items():
if key == kitten:
changed = True
kitten = expanded[0]
if len(expanded) > 1:
rest = expanded[1] + ' ' + rest
if changed:
self.action = self.action._replace(args=[kitten + (' ' + rest).rstrip()])
def parse_key(val, key_definitions): def parse_key(val, key_definitions):
parts = val.split(maxsplit=1) parts = val.split(maxsplit=1)
@@ -385,6 +386,13 @@ def handle_symbol_map(key, val, ans):
ans['symbol_map'].update(parse_symbol_map(val)) ans['symbol_map'].update(parse_symbol_map(val))
@special_handler
def handle_kitten_alias(key, val, ans):
parts = val.split(maxsplit=2)
if len(parts) >= 2:
ans['kitten_aliases'][parts[0]] = parts[1:]
@special_handler @special_handler
def handle_send_text(key, val, ans): def handle_send_text(key, val, ans):
# For legacy compatibility # For legacy compatibility
@@ -403,7 +411,27 @@ def handle_deprecated_hide_window_decorations_aliases(key, val, ans):
handle_deprecated_hide_window_decorations_aliases.key = True handle_deprecated_hide_window_decorations_aliases.key = True
log_error('The option {} is deprecated. Use hide_window_decorations instead.'.format(key)) log_error('The option {} is deprecated. Use hide_window_decorations instead.'.format(key))
if to_bool(val): if to_bool(val):
ans['hide_window_decorations'] = True if is_macos and key == 'macos_hide_titlebar' or (not is_macos and key == 'x11_hide_window_decorations'):
ans['hide_window_decorations'] = True
@deprecated_handler('macos_show_window_title_in_menubar')
def handle_deprecated_macos_show_window_title_in_menubar_alias(key, val, ans):
if not hasattr(handle_deprecated_macos_show_window_title_in_menubar_alias, key):
handle_deprecated_macos_show_window_title_in_menubar_alias.key = True
log_error('The option {} is deprecated. Use macos_show_window_title_in menubar instead.'.format(key))
macos_show_window_title_in = ans.get('macos_show_window_title_in', 'all')
if to_bool(val):
if macos_show_window_title_in == 'none':
macos_show_window_title_in = 'menubar'
elif macos_show_window_title_in == 'window':
macos_show_window_title_in = 'all'
else:
if macos_show_window_title_in == 'all':
macos_show_window_title_in = 'window'
elif macos_show_window_title_in == 'menubar':
macos_show_window_title_in = 'none'
ans['macos_show_window_title_in'] = macos_show_window_title_in
def expandvars(val, env): def expandvars(val, env):
@@ -443,7 +471,7 @@ def option_names_for_completion():
def parse_config(lines, check_keys=True, accumulate_bad_lines=None): def parse_config(lines, check_keys=True, accumulate_bad_lines=None):
ans = {'symbol_map': {}, 'keymap': {}, 'sequence_map': {}, 'key_definitions': [], 'env': {}} ans = {'symbol_map': {}, 'keymap': {}, 'sequence_map': {}, 'key_definitions': [], 'env': {}, 'kitten_aliases': {}}
parse_config_base( parse_config_base(
lines, lines,
defaults, defaults,
@@ -593,8 +621,11 @@ def finalize_keys(opts):
defns = [] defns = []
else: else:
defns.append(d) defns.append(d)
kitten_aliases = opts.kitten_aliases
for d in defns: for d in defns:
d.resolve(opts.kitty_mod) d.resolve(opts.kitty_mod)
if kitten_aliases and d.action.func == 'kitten':
d.resolve_kitten_aliases(kitten_aliases)
keymap = {} keymap = {}
sequence_map = {} sequence_map = {}
@@ -628,6 +659,4 @@ def load_config(*paths, overrides=None, accumulate_bad_lines=None):
if opts.background_opacity < 1.0 and opts.macos_titlebar_color: if opts.background_opacity < 1.0 and opts.macos_titlebar_color:
log_error('Cannot use both macos_titlebar_color and background_opacity') log_error('Cannot use both macos_titlebar_color and background_opacity')
opts.macos_titlebar_color = 0 opts.macos_titlebar_color = 0
if (is_macos and getattr(opts, 'macos_hide_titlebar', False)) or (not is_macos and getattr(opts, 'x11_hide_window_decorations', False)):
opts.hide_window_decorations = True
return opts return opts

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