Compare commits
34 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
62db7639a8 | ||
|
|
80f3fe6e9f | ||
|
|
9ba2c4b397 | ||
|
|
bfa53d4b45 | ||
|
|
69f3ceb903 | ||
|
|
d0f839bbd8 | ||
|
|
48538c0e25 | ||
|
|
02ab22f08c | ||
|
|
b3b216a6dc | ||
|
|
431564c8bc | ||
|
|
57f1bbb71a | ||
|
|
faac8649e4 | ||
|
|
1e6a41186f | ||
|
|
eddee67130 | ||
|
|
9b834014e9 | ||
|
|
a467e79144 | ||
|
|
90cc785b55 | ||
|
|
09710425ab | ||
|
|
dd36727adf | ||
|
|
47b665a624 | ||
|
|
7011329761 | ||
|
|
ea24c23fde | ||
|
|
be8f2b8106 | ||
|
|
71db024a3b | ||
|
|
3790af6897 | ||
|
|
dc6ef63ddd | ||
|
|
ef762f7a2b | ||
|
|
4ed646e062 | ||
|
|
afbd843388 | ||
|
|
18c3598ef2 | ||
|
|
1c2623e609 | ||
|
|
e232863028 | ||
|
|
a89309153d | ||
|
|
fee7c8e573 |
@@ -3,6 +3,31 @@ 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.
|
||||||
|
|
||||||
|
version 0.8.3 [2018-03-29]
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
- Fix a regression that broke the visual bell and invert screen colors escape
|
||||||
|
code
|
||||||
|
|
||||||
|
- Allow double-click and triple-click + drag to extend selections word at a
|
||||||
|
time or line at a time
|
||||||
|
|
||||||
|
- Add a keyboard shortcut to set the tab title
|
||||||
|
|
||||||
|
- Fix setting window title to empty via OSC escape code not working correctly
|
||||||
|
|
||||||
|
- Linux: Fix cell width calculation incorrect for some fonts (cell widths are
|
||||||
|
now calculated by actually rendering bitmaps, which is slower but more
|
||||||
|
accurate)
|
||||||
|
|
||||||
|
- Allow specifying a system wide kitty config file, for all users
|
||||||
|
|
||||||
|
- Add a --debug-config command line flag to output data about the system and
|
||||||
|
kitty configuration.
|
||||||
|
|
||||||
|
- Wayland: Fix auto-repeat of keys not working
|
||||||
|
|
||||||
|
|
||||||
version 0.8.2 [2018-03-17]
|
version 0.8.2 [2018-03-17]
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
|
|||||||
@@ -39,6 +39,7 @@
|
|||||||
:sc_scroll_page_down: pass:quotes[`ctrl+shift+page_down`]
|
:sc_scroll_page_down: pass:quotes[`ctrl+shift+page_down`]
|
||||||
:sc_scroll_page_up: pass:quotes[`ctrl+shift+page_up`]
|
:sc_scroll_page_up: pass:quotes[`ctrl+shift+page_up`]
|
||||||
:sc_second_window: pass:quotes[`ctrl+shift+2`]
|
:sc_second_window: pass:quotes[`ctrl+shift+2`]
|
||||||
|
:sc_set_tab_title: pass:quotes[`ctrl+shift+alt+t`]
|
||||||
:sc_seventh_window: pass:quotes[`ctrl+shift+7`]
|
:sc_seventh_window: pass:quotes[`ctrl+shift+7`]
|
||||||
:sc_show_scrollback: pass:quotes[`ctrl+shift+h`]
|
:sc_show_scrollback: pass:quotes[`ctrl+shift+h`]
|
||||||
:sc_sixth_window: pass:quotes[`ctrl+shift+6`]
|
:sc_sixth_window: pass:quotes[`ctrl+shift+6`]
|
||||||
@@ -132,6 +133,8 @@ python3 .
|
|||||||
|
|
||||||
* Gentoo: https://packages.gentoo.org/packages/x11-terms/kitty
|
* Gentoo: https://packages.gentoo.org/packages/x11-terms/kitty
|
||||||
|
|
||||||
|
* openSUSE: https://build.opensuse.org/package/show/X11:terminals/kitty
|
||||||
|
|
||||||
=== macOS packages
|
=== macOS packages
|
||||||
|
|
||||||
kitty is available as a macOS `dmg` file for easy installation from the
|
kitty is available as a macOS `dmg` file for easy installation from the
|
||||||
@@ -200,6 +203,7 @@ windows are:
|
|||||||
|Next layout | {sc_next_layout}
|
|Next layout | {sc_next_layout}
|
||||||
|Move tab forward | {sc_move_tab_forward}
|
|Move tab forward | {sc_move_tab_forward}
|
||||||
|Move tab backward | {sc_move_tab_backward}
|
|Move tab backward | {sc_move_tab_backward}
|
||||||
|
|Set tab title | {sc_set_tab_title}
|
||||||
|
|
||||||
|===
|
|===
|
||||||
|
|
||||||
@@ -317,11 +321,15 @@ a pull request!
|
|||||||
|
|
||||||
kitty is highly customizable, everything from keyboard shortcuts, to painting
|
kitty is highly customizable, everything from keyboard shortcuts, to painting
|
||||||
frames-per-second. See the heavily commented link:kitty/kitty.conf[default
|
frames-per-second. See the heavily commented link:kitty/kitty.conf[default
|
||||||
config file]. By default kitty looks for a config file in the OS config
|
config file] for an overview of all customization possibilities.
|
||||||
directory (usually `~/.config/kitty/kitty.conf` on Linux and
|
|
||||||
|
By default kitty looks for a config file in the OS config directories (usually
|
||||||
|
`~/.config/kitty/kitty.conf` and additionally
|
||||||
`~/Library/Preferences/kitty/kitty.conf` on macOS) but you can pass a specific
|
`~/Library/Preferences/kitty/kitty.conf` on macOS) but you can pass a specific
|
||||||
path via the `--config` option or use the `KITTY_CONFIG_DIRECTORY` environment
|
path via the `--config` option or use the `KITTY_CONFIG_DIRECTORY` environment
|
||||||
variable.
|
variable. See the help for the `--config` option in `kitty --help` for full
|
||||||
|
details.
|
||||||
|
|
||||||
|
|
||||||
== Startup Sessions
|
== Startup Sessions
|
||||||
|
|
||||||
@@ -438,6 +446,8 @@ installs the terminfo file and `kitty` that installs the main program.
|
|||||||
This allows users to install the terminfo file on servers into which they ssh,
|
This allows users to install the terminfo file on servers into which they ssh,
|
||||||
without needing to install all of kitty.
|
without needing to install all of kitty.
|
||||||
|
|
||||||
|
You also need `tic` to compile the terminfo files, it is usually found in the development package of `ncurses`
|
||||||
|
|
||||||
This applies to creating packages for kitty for macOS package managers such as
|
This applies to creating packages for kitty for macOS package managers such as
|
||||||
brew or MacPorts as well.
|
brew or MacPorts as well.
|
||||||
|
|
||||||
@@ -464,7 +474,7 @@ makes use of the extra cell to render them in two cells.
|
|||||||
|
|
||||||
=== How do I build kitty.app on macOS?
|
=== How do I build kitty.app on macOS?
|
||||||
|
|
||||||
Install `optipng` and `librsvg` using `brew` or similar (needed for the logo generation step).
|
Install `imagemagick`, `optipng` and `librsvg` using `brew` or similar (needed for the logo generation step).
|
||||||
|
|
||||||
And run:
|
And run:
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -582,6 +582,9 @@ static const NSRange kEmptyRange = { NSNotFound, 0 };
|
|||||||
window->ns.xscale = xscale;
|
window->ns.xscale = xscale;
|
||||||
window->ns.yscale = yscale;
|
window->ns.yscale = yscale;
|
||||||
_glfwInputWindowContentScale(window, xscale, yscale);
|
_glfwInputWindowContentScale(window, xscale, yscale);
|
||||||
|
|
||||||
|
if (window->ns.layer)
|
||||||
|
[window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1358,7 +1361,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
[NSApp requestUserAttention:NSInformationalRequest];
|
[NSApp requestUserAttention:NSInformationalRequest];
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window, int64_t param)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
NSBeep();
|
NSBeep();
|
||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
@@ -1871,6 +1874,7 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
return VK_ERROR_EXTENSION_NOT_PRESENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[window->ns.layer setContentsScale:[window->ns.object backingScaleFactor]];
|
||||||
[window->ns.view setWantsLayer:YES];
|
[window->ns.view setWantsLayer:YES];
|
||||||
|
|
||||||
memset(&sci, 0, sizeof(sci));
|
memset(&sci, 0, sizeof(sci));
|
||||||
@@ -1902,4 +1906,3 @@ GLFWAPI id glfwGetCocoaWindow(GLFWwindow* handle)
|
|||||||
_GLFW_REQUIRE_INIT_OR_RETURN(nil);
|
_GLFW_REQUIRE_INIT_OR_RETURN(nil);
|
||||||
return window->ns.object;
|
return window->ns.object;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
13
glfw/glfw.py
13
glfw/glfw.py
@@ -10,6 +10,10 @@ import sys
|
|||||||
|
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_macos = 'darwin' in _plat
|
is_macos = 'darwin' in _plat
|
||||||
|
is_freebsd = 'freebsd' in _plat
|
||||||
|
is_netbsd = 'netbsd' in _plat
|
||||||
|
is_dragonflybsd = 'dragonfly' in _plat
|
||||||
|
is_bsd = is_freebsd or is_netbsd or is_dragonflybsd
|
||||||
base = os.path.dirname(os.path.abspath(__file__))
|
base = os.path.dirname(os.path.abspath(__file__))
|
||||||
|
|
||||||
|
|
||||||
@@ -100,13 +104,14 @@ def collect_source_information():
|
|||||||
'common': dict(extract_sources('common')),
|
'common': dict(extract_sources('common')),
|
||||||
'wayland_protocols': wayland_protocols,
|
'wayland_protocols': wayland_protocols,
|
||||||
}
|
}
|
||||||
|
joystick = 'null' if is_bsd else 'linux'
|
||||||
for group in 'cocoa win32 x11 wayland osmesa'.split():
|
for group in 'cocoa win32 x11 wayland osmesa'.split():
|
||||||
m = re.search('_GLFW_' + group.upper(), raw)
|
m = re.search('_GLFW_' + group.upper(), raw)
|
||||||
ans[group] = dict(extract_sources('glfw', m.start()))
|
ans[group] = dict(extract_sources('glfw', m.start()))
|
||||||
if group == 'x11':
|
if group in ('x11', 'wayland'):
|
||||||
ans[group]['headers'].append('linux_joystick.h')
|
ans[group]['headers'].append('{}_joystick.h'.format(joystick))
|
||||||
ans[group]['sources'].append('linux_joystick.c')
|
ans[group]['sources'].append('{}_joystick.c'.format(joystick))
|
||||||
elif group == 'wayland':
|
if group == 'wayland':
|
||||||
ans[group]['protocols'] = p = []
|
ans[group]['protocols'] = p = []
|
||||||
for m in re.finditer(r'WAYLAND_PROTOCOLS_PKGDATADIR\}/(.+?)"?$', raw, flags=re.M):
|
for m in re.finditer(r'WAYLAND_PROTOCOLS_PKGDATADIR\}/(.+?)"?$', raw, flags=re.M):
|
||||||
p.append(m.group(1))
|
p.append(m.group(1))
|
||||||
|
|||||||
11
glfw/glfw3.h
vendored
11
glfw/glfw3.h
vendored
@@ -3188,13 +3188,9 @@ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window);
|
|||||||
/*! @brief Sounds an audible bell associated with the window
|
/*! @brief Sounds an audible bell associated with the window
|
||||||
*
|
*
|
||||||
* This function sounds an audible bell, on platforms where it is
|
* This function sounds an audible bell, on platforms where it is
|
||||||
* supported. Currently (macOS, Windows and X11).
|
* supported. Currently (macOS, Windows, X11 and Wayland).
|
||||||
*
|
*
|
||||||
* @param[in] window The window with which the bell is associated.
|
* @param[in] window The window with which the bell is associated.
|
||||||
* @param[in] param The meaning of this parameter is platform dependent. On
|
|
||||||
* X11 it corresponds to the percentage controlling bell volume (see man
|
|
||||||
* XBell). On Windows it is the type of sound to make, see the MSDN docs for
|
|
||||||
* MessageBeep. On macOS, it is ignored.
|
|
||||||
* @return GLFW_TRUE if the bell succeeded otherwise GLFW_FALSE
|
* @return GLFW_TRUE if the bell succeeded otherwise GLFW_FALSE
|
||||||
*
|
*
|
||||||
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
* @errors Possible errors include @ref GLFW_NOT_INITIALIZED and @ref
|
||||||
@@ -3209,7 +3205,7 @@ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* window);
|
|||||||
*
|
*
|
||||||
* @ingroup window
|
* @ingroup window
|
||||||
*/
|
*/
|
||||||
GLFWAPI int glfwWindowBell(GLFWwindow* window, int64_t param);
|
GLFWAPI int glfwWindowBell(GLFWwindow* window);
|
||||||
|
|
||||||
|
|
||||||
/*! @brief Returns the monitor that the window uses for full screen mode.
|
/*! @brief Returns the monitor that the window uses for full screen mode.
|
||||||
@@ -4901,7 +4897,7 @@ GLFWAPI const char* glfwGetGamepadName(int jid);
|
|||||||
*
|
*
|
||||||
* Not all devices have all the buttons or axes provided by @ref
|
* Not all devices have all the buttons or axes provided by @ref
|
||||||
* GLFWgamepadstate. Unavailable buttons and axes will always report
|
* GLFWgamepadstate. Unavailable buttons and axes will always report
|
||||||
* `GLFW_RELEASE` and 1.0 respectively.
|
* `GLFW_RELEASE` and 0.0 respectively.
|
||||||
*
|
*
|
||||||
* @param[in] jid The [joystick](@ref joysticks) to query.
|
* @param[in] jid The [joystick](@ref joysticks) to query.
|
||||||
* @param[out] state The gamepad input state of the joystick.
|
* @param[out] state The gamepad input state of the joystick.
|
||||||
@@ -5546,4 +5542,3 @@ GLFWAPI VkResult glfwCreateWindowSurface(VkInstance instance, GLFWwindow* window
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif /* _glfw3_h_ */
|
#endif /* _glfw3_h_ */
|
||||||
|
|
||||||
|
|||||||
5
glfw/internal.h
vendored
5
glfw/internal.h
vendored
@@ -128,7 +128,7 @@ typedef enum VkStructureType
|
|||||||
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
VK_STRUCTURE_TYPE_WAYLAND_SURFACE_CREATE_INFO_KHR = 1000006000,
|
||||||
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
VK_STRUCTURE_TYPE_MIR_SURFACE_CREATE_INFO_KHR = 1000007000,
|
||||||
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
VK_STRUCTURE_TYPE_WIN32_SURFACE_CREATE_INFO_KHR = 1000009000,
|
||||||
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000053000,
|
VK_STRUCTURE_TYPE_MACOS_SURFACE_CREATE_INFO_MVK = 1000123000,
|
||||||
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
VK_STRUCTURE_TYPE_MAX_ENUM = 0x7FFFFFFF
|
||||||
} VkStructureType;
|
} VkStructureType;
|
||||||
|
|
||||||
@@ -653,7 +653,7 @@ void _glfwPlatformMaximizeWindow(_GLFWwindow* window);
|
|||||||
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
void _glfwPlatformShowWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformHideWindow(_GLFWwindow* window);
|
void _glfwPlatformHideWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
|
void _glfwPlatformRequestWindowAttention(_GLFWwindow* window);
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window, int64_t);
|
int _glfwPlatformWindowBell(_GLFWwindow* window);
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
void _glfwPlatformFocusWindow(_GLFWwindow* window);
|
||||||
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
void _glfwPlatformSetWindowMonitor(_GLFWwindow* window, _GLFWmonitor* monitor,
|
||||||
int xpos, int ypos, int width, int height,
|
int xpos, int ypos, int width, int height,
|
||||||
@@ -769,4 +769,3 @@ void _glfwTerminateVulkan(void);
|
|||||||
const char* _glfwGetVulkanResultString(VkResult result);
|
const char* _glfwGetVulkanResultString(VkResult result);
|
||||||
|
|
||||||
char* _glfw_strdup(const char* source);
|
char* _glfw_strdup(const char* source);
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ GLFWbool _glfwCreateContextNSGL(_GLFWwindow* window,
|
|||||||
// Info.plist for unbundled applications
|
// Info.plist for unbundled applications
|
||||||
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
// HACK: This assumes that NSOpenGLPixelFormat will remain
|
||||||
// a straightforward wrapper of its CGL counterpart
|
// a straightforward wrapper of its CGL counterpart
|
||||||
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 100800
|
#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
|
||||||
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
addAttrib(kCGLPFASupportsAutomaticGraphicsSwitching);
|
||||||
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
#endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/
|
||||||
}
|
}
|
||||||
|
|||||||
3
glfw/null_window.c
vendored
3
glfw/null_window.c
vendored
@@ -205,7 +205,7 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window, int64_t param)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
@@ -323,4 +323,3 @@ VkResult _glfwPlatformCreateWindowSurface(VkInstance instance,
|
|||||||
// 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -55,12 +55,13 @@
|
|||||||
"wayland": {
|
"wayland": {
|
||||||
"headers": [
|
"headers": [
|
||||||
"wl_platform.h",
|
"wl_platform.h",
|
||||||
"linux_joystick.h",
|
|
||||||
"posix_time.h",
|
"posix_time.h",
|
||||||
"posix_thread.h",
|
"posix_thread.h",
|
||||||
|
"xkb_glfw.h",
|
||||||
"xkb_unicode.h",
|
"xkb_unicode.h",
|
||||||
"egl_context.h",
|
"egl_context.h",
|
||||||
"osmesa_context.h"
|
"osmesa_context.h",
|
||||||
|
"linux_joystick.h"
|
||||||
],
|
],
|
||||||
"protocols": [
|
"protocols": [
|
||||||
"stable/xdg-shell/xdg-shell.xml",
|
"stable/xdg-shell/xdg-shell.xml",
|
||||||
@@ -73,12 +74,12 @@
|
|||||||
"wl_init.c",
|
"wl_init.c",
|
||||||
"wl_monitor.c",
|
"wl_monitor.c",
|
||||||
"wl_window.c",
|
"wl_window.c",
|
||||||
"linux_joystick.c",
|
|
||||||
"posix_time.c",
|
"posix_time.c",
|
||||||
"posix_thread.c",
|
"posix_thread.c",
|
||||||
"xkb_unicode.c",
|
"xkb_unicode.c",
|
||||||
"egl_context.c",
|
"egl_context.c",
|
||||||
"osmesa_context.c"
|
"osmesa_context.c",
|
||||||
|
"linux_joystick.c"
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"wayland_protocols": [
|
"wayland_protocols": [
|
||||||
|
|||||||
5
glfw/win32_window.c
vendored
5
glfw/win32_window.c
vendored
@@ -1474,9 +1474,9 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
FlashWindow(window->win32.handle, TRUE);
|
FlashWindow(window->win32.handle, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window, int64_t param)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return MessageBeep(0xFFFFFFFF & param) ? GLFW_TRUE : GLFW_FALSE;
|
return MessageBeep(0xFFFFFFFF) ? GLFW_TRUE : GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
@@ -2014,4 +2014,3 @@ GLFWAPI HWND glfwGetWin32Window(GLFWwindow* handle)
|
|||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return window->win32.handle;
|
return window->win32.handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
glfw/window.c
vendored
5
glfw/window.c
vendored
@@ -768,14 +768,14 @@ GLFWAPI void glfwRequestWindowAttention(GLFWwindow* handle)
|
|||||||
_glfwPlatformRequestWindowAttention(window);
|
_glfwPlatformRequestWindowAttention(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI int glfwWindowBell(GLFWwindow* handle, int64_t param)
|
GLFWAPI int glfwWindowBell(GLFWwindow* handle)
|
||||||
{
|
{
|
||||||
_GLFWwindow* window = (_GLFWwindow*) handle;
|
_GLFWwindow* window = (_GLFWwindow*) handle;
|
||||||
assert(window != NULL);
|
assert(window != NULL);
|
||||||
|
|
||||||
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
_GLFW_REQUIRE_INIT_OR_RETURN(GLFW_FALSE);
|
||||||
|
|
||||||
return _glfwPlatformWindowBell(window, param);
|
return _glfwPlatformWindowBell(window);
|
||||||
}
|
}
|
||||||
|
|
||||||
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
GLFWAPI void glfwHideWindow(GLFWwindow* handle)
|
||||||
@@ -1106,4 +1106,3 @@ GLFWAPI void glfwPostEmptyEvent(void)
|
|||||||
|
|
||||||
_glfwPlatformPostEmptyEvent();
|
_glfwPlatformPostEmptyEvent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
377
glfw/wl_init.c
vendored
377
glfw/wl_init.c
vendored
@@ -32,7 +32,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
|
|
||||||
@@ -350,16 +349,7 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
int fd,
|
int fd,
|
||||||
uint32_t size)
|
uint32_t size)
|
||||||
{
|
{
|
||||||
struct xkb_keymap* keymap;
|
|
||||||
struct xkb_state* state;
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
struct xkb_compose_table* composeTable;
|
|
||||||
struct xkb_compose_state* composeState;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
char* mapStr;
|
char* mapStr;
|
||||||
const char* locale;
|
|
||||||
|
|
||||||
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
if (format != WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1)
|
||||||
{
|
{
|
||||||
@@ -372,78 +362,10 @@ static void keyboardHandleKeymap(void* data,
|
|||||||
close(fd);
|
close(fd);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
xkb_glfw_compile_keymap(mapStr);
|
||||||
keymap = xkb_keymap_new_from_string(_glfw.wl.xkb.context,
|
|
||||||
mapStr,
|
|
||||||
XKB_KEYMAP_FORMAT_TEXT_V1,
|
|
||||||
0);
|
|
||||||
munmap(mapStr, size);
|
munmap(mapStr, size);
|
||||||
close(fd);
|
close(fd);
|
||||||
|
|
||||||
if (!keymap)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to compile keymap");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
state = xkb_state_new(keymap);
|
|
||||||
if (!state)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to create XKB state");
|
|
||||||
xkb_keymap_unref(keymap);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Look up the preferred locale, falling back to "C" as default.
|
|
||||||
locale = getenv("LC_ALL");
|
|
||||||
if (!locale)
|
|
||||||
locale = getenv("LC_CTYPE");
|
|
||||||
if (!locale)
|
|
||||||
locale = getenv("LANG");
|
|
||||||
if (!locale)
|
|
||||||
locale = "C";
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
composeTable =
|
|
||||||
xkb_compose_table_new_from_locale(_glfw.wl.xkb.context, locale,
|
|
||||||
XKB_COMPOSE_COMPILE_NO_FLAGS);
|
|
||||||
if (composeTable)
|
|
||||||
{
|
|
||||||
composeState =
|
|
||||||
xkb_compose_state_new(composeTable, XKB_COMPOSE_STATE_NO_FLAGS);
|
|
||||||
xkb_compose_table_unref(composeTable);
|
|
||||||
if (composeState)
|
|
||||||
_glfw.wl.xkb.composeState = composeState;
|
|
||||||
else
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to create XKB compose state");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to create XKB compose table");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
|
||||||
_glfw.wl.xkb.keymap = keymap;
|
|
||||||
_glfw.wl.xkb.state = state;
|
|
||||||
|
|
||||||
_glfw.wl.xkb.controlMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Control");
|
|
||||||
_glfw.wl.xkb.altMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod1");
|
|
||||||
_glfw.wl.xkb.shiftMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Shift");
|
|
||||||
_glfw.wl.xkb.superMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod4");
|
|
||||||
_glfw.wl.xkb.capsLockMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Lock");
|
|
||||||
_glfw.wl.xkb.numLockMask =
|
|
||||||
1 << xkb_keymap_mod_get_index(_glfw.wl.xkb.keymap, "Mod2");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleEnter(void* data,
|
static void keyboardHandleEnter(void* data,
|
||||||
@@ -482,15 +404,6 @@ static void keyboardHandleLeave(void* data,
|
|||||||
_glfwInputWindowFocus(window, GLFW_FALSE);
|
_glfwInputWindowFocus(window, GLFW_FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int toGLFWKeyCode(uint32_t key)
|
|
||||||
{
|
|
||||||
if (key < sizeof(_glfw.wl.keycodes) / sizeof(_glfw.wl.keycodes[0]))
|
|
||||||
return _glfw.wl.keycodes[key];
|
|
||||||
|
|
||||||
return GLFW_KEY_UNKNOWN;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
||||||
{
|
{
|
||||||
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
if (sym == XKB_KEY_NoSymbol || !_glfw.wl.xkb.composeState)
|
||||||
@@ -510,9 +423,8 @@ static xkb_keysym_t composeSymbol(xkb_keysym_t sym)
|
|||||||
return sym;
|
return sym;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
|
static void inputChar(_GLFWwindow* window, uint32_t key, GLFWbool *shouldRepeat)
|
||||||
{
|
{
|
||||||
uint32_t code, numSyms;
|
uint32_t code, numSyms;
|
||||||
long cp;
|
long cp;
|
||||||
@@ -521,24 +433,23 @@ static GLFWbool inputChar(_GLFWwindow* window, uint32_t key)
|
|||||||
|
|
||||||
code = key + 8;
|
code = key + 8;
|
||||||
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
numSyms = xkb_state_key_get_syms(_glfw.wl.xkb.state, code, &syms);
|
||||||
|
*shouldRepeat = xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, code);
|
||||||
|
|
||||||
if (numSyms == 1)
|
if (numSyms == 1)
|
||||||
{
|
{
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
sym = composeSymbol(syms[0]);
|
sym = composeSymbol(syms[0]);
|
||||||
#else
|
|
||||||
sym = syms[0];
|
|
||||||
#endif
|
|
||||||
cp = _glfwKeySym2Unicode(sym);
|
cp = _glfwKeySym2Unicode(sym);
|
||||||
if (cp != -1)
|
if (cp != -1)
|
||||||
{
|
{
|
||||||
const int mods = _glfw.wl.xkb.modifiers;
|
const int mods = _glfw.wl.xkb.modifiers;
|
||||||
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
const int plain = !(mods & (GLFW_MOD_CONTROL | GLFW_MOD_ALT));
|
||||||
|
if (*shouldRepeat) {
|
||||||
|
_glfw.wl.keyRepeatInfo.codepoint = cp;
|
||||||
|
_glfw.wl.keyRepeatInfo.plain = plain;
|
||||||
|
}
|
||||||
_glfwInputChar(window, cp, mods, plain);
|
_glfwInputChar(window, cp, mods, plain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return xkb_keymap_key_repeats(_glfw.wl.xkb.keymap, syms[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleKey(void* data,
|
static void keyboardHandleKey(void* data,
|
||||||
@@ -551,34 +462,32 @@ static void keyboardHandleKey(void* data,
|
|||||||
int keyCode;
|
int keyCode;
|
||||||
int action;
|
int action;
|
||||||
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
_GLFWwindow* window = _glfw.wl.keyboardFocus;
|
||||||
GLFWbool shouldRepeat;
|
|
||||||
struct itimerspec timer = {};
|
|
||||||
|
|
||||||
if (!window)
|
if (!window)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
keyCode = toGLFWKeyCode(key);
|
keyCode = xkb_glfw_to_glfw_key_code(key);
|
||||||
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
|
action = state == WL_KEYBOARD_KEY_STATE_PRESSED
|
||||||
? GLFW_PRESS : GLFW_RELEASE;
|
? GLFW_PRESS : GLFW_RELEASE;
|
||||||
|
_glfw.wl.keyRepeatInfo.nextRepeatAt = 0;
|
||||||
|
_glfw.wl.keyRepeatInfo.codepoint = -1;
|
||||||
|
|
||||||
_glfwInputKey(window, keyCode, key, action,
|
_glfwInputKey(window, keyCode, key, action,
|
||||||
_glfw.wl.xkb.modifiers);
|
_glfw.wl.xkb.modifiers);
|
||||||
|
|
||||||
if (action == GLFW_PRESS)
|
if (action == GLFW_PRESS)
|
||||||
{
|
{
|
||||||
shouldRepeat = inputChar(window, key);
|
GLFWbool shouldRepeat = GLFW_FALSE;
|
||||||
|
inputChar(window, key, &shouldRepeat);
|
||||||
|
|
||||||
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
if (shouldRepeat && _glfw.wl.keyboardRepeatRate > 0)
|
||||||
{
|
{
|
||||||
_glfw.wl.keyboardLastKey = keyCode;
|
_glfw.wl.keyRepeatInfo.glfwKeyCode = keyCode;
|
||||||
_glfw.wl.keyboardLastScancode = key;
|
_glfw.wl.keyRepeatInfo.scancode = key;
|
||||||
timer.it_interval.tv_sec = _glfw.wl.keyboardRepeatRate / 1000;
|
_glfw.wl.keyRepeatInfo.nextRepeatAt = glfwGetTime() + (double)(_glfw.wl.keyboardRepeatDelay) / 1000.0;
|
||||||
timer.it_interval.tv_nsec = (_glfw.wl.keyboardRepeatRate % 1000) * 1000000;
|
_glfw.wl.keyRepeatInfo.keyboardFocus = window;
|
||||||
timer.it_value.tv_sec = _glfw.wl.keyboardRepeatDelay / 1000;
|
|
||||||
timer.it_value.tv_nsec = (_glfw.wl.keyboardRepeatDelay % 1000) * 1000000;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
timerfd_settime(_glfw.wl.timerfd, 0, &timer, NULL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void keyboardHandleModifiers(void* data,
|
static void keyboardHandleModifiers(void* data,
|
||||||
@@ -589,41 +498,9 @@ static void keyboardHandleModifiers(void* data,
|
|||||||
uint32_t modsLocked,
|
uint32_t modsLocked,
|
||||||
uint32_t group)
|
uint32_t group)
|
||||||
{
|
{
|
||||||
xkb_mod_mask_t mask;
|
xkb_glfw_update_modifiers(modsDepressed, modsLatched, modsLocked, group);
|
||||||
unsigned int modifiers = 0;
|
|
||||||
|
|
||||||
if (!_glfw.wl.xkb.keymap)
|
|
||||||
return;
|
|
||||||
|
|
||||||
xkb_state_update_mask(_glfw.wl.xkb.state,
|
|
||||||
modsDepressed,
|
|
||||||
modsLatched,
|
|
||||||
modsLocked,
|
|
||||||
0,
|
|
||||||
0,
|
|
||||||
group);
|
|
||||||
|
|
||||||
mask = xkb_state_serialize_mods(_glfw.wl.xkb.state,
|
|
||||||
XKB_STATE_MODS_DEPRESSED |
|
|
||||||
XKB_STATE_LAYOUT_DEPRESSED |
|
|
||||||
XKB_STATE_MODS_LATCHED |
|
|
||||||
XKB_STATE_LAYOUT_LATCHED);
|
|
||||||
if (mask & _glfw.wl.xkb.controlMask)
|
|
||||||
modifiers |= GLFW_MOD_CONTROL;
|
|
||||||
if (mask & _glfw.wl.xkb.altMask)
|
|
||||||
modifiers |= GLFW_MOD_ALT;
|
|
||||||
if (mask & _glfw.wl.xkb.shiftMask)
|
|
||||||
modifiers |= GLFW_MOD_SHIFT;
|
|
||||||
if (mask & _glfw.wl.xkb.superMask)
|
|
||||||
modifiers |= GLFW_MOD_SUPER;
|
|
||||||
if (mask & _glfw.wl.xkb.capsLockMask)
|
|
||||||
modifiers |= GLFW_MOD_CAPS_LOCK;
|
|
||||||
if (mask & _glfw.wl.xkb.numLockMask)
|
|
||||||
modifiers |= GLFW_MOD_NUM_LOCK;
|
|
||||||
_glfw.wl.xkb.modifiers = modifiers;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
|
||||||
static void keyboardHandleRepeatInfo(void* data,
|
static void keyboardHandleRepeatInfo(void* data,
|
||||||
struct wl_keyboard* keyboard,
|
struct wl_keyboard* keyboard,
|
||||||
int32_t rate,
|
int32_t rate,
|
||||||
@@ -635,7 +512,6 @@ static void keyboardHandleRepeatInfo(void* data,
|
|||||||
_glfw.wl.keyboardRepeatRate = rate;
|
_glfw.wl.keyboardRepeatRate = rate;
|
||||||
_glfw.wl.keyboardRepeatDelay = delay;
|
_glfw.wl.keyboardRepeatDelay = delay;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
|
||||||
static const struct wl_keyboard_listener keyboardListener = {
|
static const struct wl_keyboard_listener keyboardListener = {
|
||||||
keyboardHandleKeymap,
|
keyboardHandleKeymap,
|
||||||
@@ -643,9 +519,7 @@ static const struct wl_keyboard_listener keyboardListener = {
|
|||||||
keyboardHandleLeave,
|
keyboardHandleLeave,
|
||||||
keyboardHandleKey,
|
keyboardHandleKey,
|
||||||
keyboardHandleModifiers,
|
keyboardHandleModifiers,
|
||||||
#ifdef WL_KEYBOARD_REPEAT_INFO_SINCE_VERSION
|
|
||||||
keyboardHandleRepeatInfo,
|
keyboardHandleRepeatInfo,
|
||||||
#endif
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void seatHandleCapabilities(void* data,
|
static void seatHandleCapabilities(void* data,
|
||||||
@@ -798,140 +672,6 @@ static const struct wl_registry_listener registryListener = {
|
|||||||
registryHandleGlobalRemove
|
registryHandleGlobalRemove
|
||||||
};
|
};
|
||||||
|
|
||||||
// Create key code translation tables
|
|
||||||
//
|
|
||||||
static void createKeyTables(void)
|
|
||||||
{
|
|
||||||
int scancode;
|
|
||||||
|
|
||||||
memset(_glfw.wl.keycodes, -1, sizeof(_glfw.wl.keycodes));
|
|
||||||
memset(_glfw.wl.scancodes, -1, sizeof(_glfw.wl.scancodes));
|
|
||||||
|
|
||||||
_glfw.wl.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT;
|
|
||||||
_glfw.wl.keycodes[KEY_1] = GLFW_KEY_1;
|
|
||||||
_glfw.wl.keycodes[KEY_2] = GLFW_KEY_2;
|
|
||||||
_glfw.wl.keycodes[KEY_3] = GLFW_KEY_3;
|
|
||||||
_glfw.wl.keycodes[KEY_4] = GLFW_KEY_4;
|
|
||||||
_glfw.wl.keycodes[KEY_5] = GLFW_KEY_5;
|
|
||||||
_glfw.wl.keycodes[KEY_6] = GLFW_KEY_6;
|
|
||||||
_glfw.wl.keycodes[KEY_7] = GLFW_KEY_7;
|
|
||||||
_glfw.wl.keycodes[KEY_8] = GLFW_KEY_8;
|
|
||||||
_glfw.wl.keycodes[KEY_9] = GLFW_KEY_9;
|
|
||||||
_glfw.wl.keycodes[KEY_0] = GLFW_KEY_0;
|
|
||||||
_glfw.wl.keycodes[KEY_SPACE] = GLFW_KEY_SPACE;
|
|
||||||
_glfw.wl.keycodes[KEY_MINUS] = GLFW_KEY_MINUS;
|
|
||||||
_glfw.wl.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL;
|
|
||||||
_glfw.wl.keycodes[KEY_Q] = GLFW_KEY_Q;
|
|
||||||
_glfw.wl.keycodes[KEY_W] = GLFW_KEY_W;
|
|
||||||
_glfw.wl.keycodes[KEY_E] = GLFW_KEY_E;
|
|
||||||
_glfw.wl.keycodes[KEY_R] = GLFW_KEY_R;
|
|
||||||
_glfw.wl.keycodes[KEY_T] = GLFW_KEY_T;
|
|
||||||
_glfw.wl.keycodes[KEY_Y] = GLFW_KEY_Y;
|
|
||||||
_glfw.wl.keycodes[KEY_U] = GLFW_KEY_U;
|
|
||||||
_glfw.wl.keycodes[KEY_I] = GLFW_KEY_I;
|
|
||||||
_glfw.wl.keycodes[KEY_O] = GLFW_KEY_O;
|
|
||||||
_glfw.wl.keycodes[KEY_P] = GLFW_KEY_P;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET;
|
|
||||||
_glfw.wl.keycodes[KEY_A] = GLFW_KEY_A;
|
|
||||||
_glfw.wl.keycodes[KEY_S] = GLFW_KEY_S;
|
|
||||||
_glfw.wl.keycodes[KEY_D] = GLFW_KEY_D;
|
|
||||||
_glfw.wl.keycodes[KEY_F] = GLFW_KEY_F;
|
|
||||||
_glfw.wl.keycodes[KEY_G] = GLFW_KEY_G;
|
|
||||||
_glfw.wl.keycodes[KEY_H] = GLFW_KEY_H;
|
|
||||||
_glfw.wl.keycodes[KEY_J] = GLFW_KEY_J;
|
|
||||||
_glfw.wl.keycodes[KEY_K] = GLFW_KEY_K;
|
|
||||||
_glfw.wl.keycodes[KEY_L] = GLFW_KEY_L;
|
|
||||||
_glfw.wl.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON;
|
|
||||||
_glfw.wl.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE;
|
|
||||||
_glfw.wl.keycodes[KEY_Z] = GLFW_KEY_Z;
|
|
||||||
_glfw.wl.keycodes[KEY_X] = GLFW_KEY_X;
|
|
||||||
_glfw.wl.keycodes[KEY_C] = GLFW_KEY_C;
|
|
||||||
_glfw.wl.keycodes[KEY_V] = GLFW_KEY_V;
|
|
||||||
_glfw.wl.keycodes[KEY_B] = GLFW_KEY_B;
|
|
||||||
_glfw.wl.keycodes[KEY_N] = GLFW_KEY_N;
|
|
||||||
_glfw.wl.keycodes[KEY_M] = GLFW_KEY_M;
|
|
||||||
_glfw.wl.keycodes[KEY_COMMA] = GLFW_KEY_COMMA;
|
|
||||||
_glfw.wl.keycodes[KEY_DOT] = GLFW_KEY_PERIOD;
|
|
||||||
_glfw.wl.keycodes[KEY_SLASH] = GLFW_KEY_SLASH;
|
|
||||||
_glfw.wl.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH;
|
|
||||||
_glfw.wl.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE;
|
|
||||||
_glfw.wl.keycodes[KEY_TAB] = GLFW_KEY_TAB;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER;
|
|
||||||
_glfw.wl.keycodes[KEY_MENU] = GLFW_KEY_MENU;
|
|
||||||
_glfw.wl.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK;
|
|
||||||
_glfw.wl.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK;
|
|
||||||
_glfw.wl.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN;
|
|
||||||
_glfw.wl.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK;
|
|
||||||
_glfw.wl.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE;
|
|
||||||
_glfw.wl.keycodes[KEY_DELETE] = GLFW_KEY_DELETE;
|
|
||||||
_glfw.wl.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE;
|
|
||||||
_glfw.wl.keycodes[KEY_ENTER] = GLFW_KEY_ENTER;
|
|
||||||
_glfw.wl.keycodes[KEY_HOME] = GLFW_KEY_HOME;
|
|
||||||
_glfw.wl.keycodes[KEY_END] = GLFW_KEY_END;
|
|
||||||
_glfw.wl.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP;
|
|
||||||
_glfw.wl.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN;
|
|
||||||
_glfw.wl.keycodes[KEY_INSERT] = GLFW_KEY_INSERT;
|
|
||||||
_glfw.wl.keycodes[KEY_LEFT] = GLFW_KEY_LEFT;
|
|
||||||
_glfw.wl.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT;
|
|
||||||
_glfw.wl.keycodes[KEY_DOWN] = GLFW_KEY_DOWN;
|
|
||||||
_glfw.wl.keycodes[KEY_UP] = GLFW_KEY_UP;
|
|
||||||
_glfw.wl.keycodes[KEY_F1] = GLFW_KEY_F1;
|
|
||||||
_glfw.wl.keycodes[KEY_F2] = GLFW_KEY_F2;
|
|
||||||
_glfw.wl.keycodes[KEY_F3] = GLFW_KEY_F3;
|
|
||||||
_glfw.wl.keycodes[KEY_F4] = GLFW_KEY_F4;
|
|
||||||
_glfw.wl.keycodes[KEY_F5] = GLFW_KEY_F5;
|
|
||||||
_glfw.wl.keycodes[KEY_F6] = GLFW_KEY_F6;
|
|
||||||
_glfw.wl.keycodes[KEY_F7] = GLFW_KEY_F7;
|
|
||||||
_glfw.wl.keycodes[KEY_F8] = GLFW_KEY_F8;
|
|
||||||
_glfw.wl.keycodes[KEY_F9] = GLFW_KEY_F9;
|
|
||||||
_glfw.wl.keycodes[KEY_F10] = GLFW_KEY_F10;
|
|
||||||
_glfw.wl.keycodes[KEY_F11] = GLFW_KEY_F11;
|
|
||||||
_glfw.wl.keycodes[KEY_F12] = GLFW_KEY_F12;
|
|
||||||
_glfw.wl.keycodes[KEY_F13] = GLFW_KEY_F13;
|
|
||||||
_glfw.wl.keycodes[KEY_F14] = GLFW_KEY_F14;
|
|
||||||
_glfw.wl.keycodes[KEY_F15] = GLFW_KEY_F15;
|
|
||||||
_glfw.wl.keycodes[KEY_F16] = GLFW_KEY_F16;
|
|
||||||
_glfw.wl.keycodes[KEY_F17] = GLFW_KEY_F17;
|
|
||||||
_glfw.wl.keycodes[KEY_F18] = GLFW_KEY_F18;
|
|
||||||
_glfw.wl.keycodes[KEY_F19] = GLFW_KEY_F19;
|
|
||||||
_glfw.wl.keycodes[KEY_F20] = GLFW_KEY_F20;
|
|
||||||
_glfw.wl.keycodes[KEY_F21] = GLFW_KEY_F21;
|
|
||||||
_glfw.wl.keycodes[KEY_F22] = GLFW_KEY_F22;
|
|
||||||
_glfw.wl.keycodes[KEY_F23] = GLFW_KEY_F23;
|
|
||||||
_glfw.wl.keycodes[KEY_F24] = GLFW_KEY_F24;
|
|
||||||
_glfw.wl.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE;
|
|
||||||
_glfw.wl.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY;
|
|
||||||
_glfw.wl.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT;
|
|
||||||
_glfw.wl.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD;
|
|
||||||
_glfw.wl.keycodes[KEY_KP0] = GLFW_KEY_KP_0;
|
|
||||||
_glfw.wl.keycodes[KEY_KP1] = GLFW_KEY_KP_1;
|
|
||||||
_glfw.wl.keycodes[KEY_KP2] = GLFW_KEY_KP_2;
|
|
||||||
_glfw.wl.keycodes[KEY_KP3] = GLFW_KEY_KP_3;
|
|
||||||
_glfw.wl.keycodes[KEY_KP4] = GLFW_KEY_KP_4;
|
|
||||||
_glfw.wl.keycodes[KEY_KP5] = GLFW_KEY_KP_5;
|
|
||||||
_glfw.wl.keycodes[KEY_KP6] = GLFW_KEY_KP_6;
|
|
||||||
_glfw.wl.keycodes[KEY_KP7] = GLFW_KEY_KP_7;
|
|
||||||
_glfw.wl.keycodes[KEY_KP8] = GLFW_KEY_KP_8;
|
|
||||||
_glfw.wl.keycodes[KEY_KP9] = GLFW_KEY_KP_9;
|
|
||||||
_glfw.wl.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL;
|
|
||||||
_glfw.wl.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL;
|
|
||||||
_glfw.wl.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER;
|
|
||||||
|
|
||||||
for (scancode = 0; scancode < 256; scancode++)
|
|
||||||
{
|
|
||||||
if (_glfw.wl.keycodes[scancode] > 0)
|
|
||||||
_glfw.wl.scancodes[_glfw.wl.keycodes[scancode]] = scancode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//////////////////////////////////////////////////////////////////////////
|
//////////////////////////////////////////////////////////////////////////
|
||||||
////// GLFW platform API //////
|
////// GLFW platform API //////
|
||||||
@@ -971,53 +711,7 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
|
_glfw.wl.egl.window_resize = (PFN_wl_egl_window_resize)
|
||||||
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
|
_glfw_dlsym(_glfw.wl.egl.handle, "wl_egl_window_resize");
|
||||||
|
|
||||||
_glfw.wl.xkb.handle = _glfw_dlopen("libxkbcommon.so.0");
|
load_glfw_xkb();
|
||||||
if (!_glfw.wl.xkb.handle)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to open libxkbcommon");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
_glfw.wl.xkb.context_new = (PFN_xkb_context_new)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_new");
|
|
||||||
_glfw.wl.xkb.context_unref = (PFN_xkb_context_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_context_unref");
|
|
||||||
_glfw.wl.xkb.keymap_new_from_string = (PFN_xkb_keymap_new_from_string)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_new_from_string");
|
|
||||||
_glfw.wl.xkb.keymap_unref = (PFN_xkb_keymap_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_unref");
|
|
||||||
_glfw.wl.xkb.keymap_mod_get_index = (PFN_xkb_keymap_mod_get_index)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_mod_get_index");
|
|
||||||
_glfw.wl.xkb.keymap_key_repeats = (PFN_xkb_keymap_key_repeats)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_keymap_key_repeats");
|
|
||||||
_glfw.wl.xkb.state_new = (PFN_xkb_state_new)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_new");
|
|
||||||
_glfw.wl.xkb.state_unref = (PFN_xkb_state_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_unref");
|
|
||||||
_glfw.wl.xkb.state_key_get_syms = (PFN_xkb_state_key_get_syms)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_key_get_syms");
|
|
||||||
_glfw.wl.xkb.state_update_mask = (PFN_xkb_state_update_mask)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_update_mask");
|
|
||||||
_glfw.wl.xkb.state_serialize_mods = (PFN_xkb_state_serialize_mods)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_state_serialize_mods");
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
_glfw.wl.xkb.compose_table_new_from_locale = (PFN_xkb_compose_table_new_from_locale)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_new_from_locale");
|
|
||||||
_glfw.wl.xkb.compose_table_unref = (PFN_xkb_compose_table_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_table_unref");
|
|
||||||
_glfw.wl.xkb.compose_state_new = (PFN_xkb_compose_state_new)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_new");
|
|
||||||
_glfw.wl.xkb.compose_state_unref = (PFN_xkb_compose_state_unref)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_unref");
|
|
||||||
_glfw.wl.xkb.compose_state_feed = (PFN_xkb_compose_state_feed)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_feed");
|
|
||||||
_glfw.wl.xkb.compose_state_get_status = (PFN_xkb_compose_state_get_status)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_status");
|
|
||||||
_glfw.wl.xkb.compose_state_get_one_sym = (PFN_xkb_compose_state_get_one_sym)
|
|
||||||
_glfw_dlsym(_glfw.wl.xkb.handle, "xkb_compose_state_get_one_sym");
|
|
||||||
#endif
|
|
||||||
|
|
||||||
_glfw.wl.display = wl_display_connect(NULL);
|
_glfw.wl.display = wl_display_connect(NULL);
|
||||||
if (!_glfw.wl.display)
|
if (!_glfw.wl.display)
|
||||||
@@ -1030,15 +724,7 @@ int _glfwPlatformInit(void)
|
|||||||
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
_glfw.wl.registry = wl_display_get_registry(_glfw.wl.display);
|
||||||
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
wl_registry_add_listener(_glfw.wl.registry, ®istryListener, NULL);
|
||||||
|
|
||||||
createKeyTables();
|
create_glfw_xkb_context();
|
||||||
|
|
||||||
_glfw.wl.xkb.context = xkb_context_new(0);
|
|
||||||
if (!_glfw.wl.xkb.context)
|
|
||||||
{
|
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
|
||||||
"Wayland: Failed to initialize xkb context");
|
|
||||||
return GLFW_FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Sync so we got all registry objects
|
// Sync so we got all registry objects
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
@@ -1046,15 +732,13 @@ int _glfwPlatformInit(void)
|
|||||||
// Sync so we got all initial output events
|
// Sync so we got all initial output events
|
||||||
wl_display_roundtrip(_glfw.wl.display);
|
wl_display_roundtrip(_glfw.wl.display);
|
||||||
|
|
||||||
|
#ifdef __linux__
|
||||||
if (!_glfwInitJoysticksLinux())
|
if (!_glfwInitJoysticksLinux())
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
|
#endif
|
||||||
|
|
||||||
_glfwInitTimerPOSIX();
|
_glfwInitTimerPOSIX();
|
||||||
|
|
||||||
_glfw.wl.timerfd = -1;
|
|
||||||
if (_glfw.wl.seatVersion >= 4)
|
|
||||||
_glfw.wl.timerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC);
|
|
||||||
|
|
||||||
if (_glfw.wl.pointer && _glfw.wl.shm)
|
if (_glfw.wl.pointer && _glfw.wl.shm)
|
||||||
{
|
{
|
||||||
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
|
_glfw.wl.cursorTheme = wl_cursor_theme_load(NULL, 32, _glfw.wl.shm);
|
||||||
@@ -1073,7 +757,9 @@ int _glfwPlatformInit(void)
|
|||||||
|
|
||||||
void _glfwPlatformTerminate(void)
|
void _glfwPlatformTerminate(void)
|
||||||
{
|
{
|
||||||
|
#ifdef __linux__
|
||||||
_glfwTerminateJoysticksLinux();
|
_glfwTerminateJoysticksLinux();
|
||||||
|
#endif
|
||||||
_glfwTerminateEGL();
|
_glfwTerminateEGL();
|
||||||
if (_glfw.wl.egl.handle)
|
if (_glfw.wl.egl.handle)
|
||||||
{
|
{
|
||||||
@@ -1081,21 +767,7 @@ void _glfwPlatformTerminate(void)
|
|||||||
_glfw.wl.egl.handle = NULL;
|
_glfw.wl.egl.handle = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
release_glfw_xkb();
|
||||||
if (_glfw.wl.xkb.composeState)
|
|
||||||
xkb_compose_state_unref(_glfw.wl.xkb.composeState);
|
|
||||||
#endif
|
|
||||||
if (_glfw.wl.xkb.keymap)
|
|
||||||
xkb_keymap_unref(_glfw.wl.xkb.keymap);
|
|
||||||
if (_glfw.wl.xkb.state)
|
|
||||||
xkb_state_unref(_glfw.wl.xkb.state);
|
|
||||||
if (_glfw.wl.xkb.context)
|
|
||||||
xkb_context_unref(_glfw.wl.xkb.context);
|
|
||||||
if (_glfw.wl.xkb.handle)
|
|
||||||
{
|
|
||||||
_glfw_dlclose(_glfw.wl.xkb.handle);
|
|
||||||
_glfw.wl.xkb.handle = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (_glfw.wl.cursorTheme)
|
if (_glfw.wl.cursorTheme)
|
||||||
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
wl_cursor_theme_destroy(_glfw.wl.cursorTheme);
|
||||||
@@ -1154,4 +826,3 @@ const char* _glfwPlatformGetVersionString(void)
|
|||||||
#endif
|
#endif
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
104
glfw/wl_platform.h
vendored
104
glfw/wl_platform.h
vendored
@@ -25,10 +25,6 @@
|
|||||||
//========================================================================
|
//========================================================================
|
||||||
|
|
||||||
#include <wayland-client.h>
|
#include <wayland-client.h>
|
||||||
#include <xkbcommon/xkbcommon.h>
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
#include <xkbcommon/xkbcommon-compose.h>
|
|
||||||
#endif
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
|
|
||||||
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
typedef VkFlags VkWaylandSurfaceCreateFlagsKHR;
|
||||||
@@ -47,7 +43,13 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
|
|||||||
|
|
||||||
#include "posix_thread.h"
|
#include "posix_thread.h"
|
||||||
#include "posix_time.h"
|
#include "posix_time.h"
|
||||||
|
#ifdef __linux__
|
||||||
#include "linux_joystick.h"
|
#include "linux_joystick.h"
|
||||||
|
#else
|
||||||
|
#include "null_joystick.h"
|
||||||
|
#endif
|
||||||
|
#define GLFW_XKB_GLOBAL_NAME _glfw.wl.xkb
|
||||||
|
#include "xkb_glfw.h"
|
||||||
#include "xkb_unicode.h"
|
#include "xkb_unicode.h"
|
||||||
#include "egl_context.h"
|
#include "egl_context.h"
|
||||||
#include "osmesa_context.h"
|
#include "osmesa_context.h"
|
||||||
@@ -101,46 +103,6 @@ typedef void (* PFN_wl_egl_window_resize)(struct wl_egl_window*, int, int, int,
|
|||||||
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
|
#define wl_egl_window_destroy _glfw.wl.egl.window_destroy
|
||||||
#define wl_egl_window_resize _glfw.wl.egl.window_resize
|
#define wl_egl_window_resize _glfw.wl.egl.window_resize
|
||||||
|
|
||||||
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
|
|
||||||
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
|
|
||||||
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
|
||||||
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
|
||||||
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
|
||||||
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
|
||||||
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
|
||||||
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
|
||||||
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
|
||||||
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
|
||||||
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
|
||||||
#define xkb_context_new _glfw.wl.xkb.context_new
|
|
||||||
#define xkb_context_unref _glfw.wl.xkb.context_unref
|
|
||||||
#define xkb_keymap_new_from_string _glfw.wl.xkb.keymap_new_from_string
|
|
||||||
#define xkb_keymap_unref _glfw.wl.xkb.keymap_unref
|
|
||||||
#define xkb_keymap_mod_get_index _glfw.wl.xkb.keymap_mod_get_index
|
|
||||||
#define xkb_keymap_key_repeats _glfw.wl.xkb.keymap_key_repeats
|
|
||||||
#define xkb_state_new _glfw.wl.xkb.state_new
|
|
||||||
#define xkb_state_unref _glfw.wl.xkb.state_unref
|
|
||||||
#define xkb_state_key_get_syms _glfw.wl.xkb.state_key_get_syms
|
|
||||||
#define xkb_state_update_mask _glfw.wl.xkb.state_update_mask
|
|
||||||
#define xkb_state_serialize_mods _glfw.wl.xkb.state_serialize_mods
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
|
||||||
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
|
||||||
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
|
||||||
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
|
|
||||||
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
|
|
||||||
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
|
|
||||||
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
|
|
||||||
#define xkb_compose_table_new_from_locale _glfw.wl.xkb.compose_table_new_from_locale
|
|
||||||
#define xkb_compose_table_unref _glfw.wl.xkb.compose_table_unref
|
|
||||||
#define xkb_compose_state_new _glfw.wl.xkb.compose_state_new
|
|
||||||
#define xkb_compose_state_unref _glfw.wl.xkb.compose_state_unref
|
|
||||||
#define xkb_compose_state_feed _glfw.wl.xkb.compose_state_feed
|
|
||||||
#define xkb_compose_state_get_status _glfw.wl.xkb.compose_state_get_status
|
|
||||||
#define xkb_compose_state_get_one_sym _glfw.wl.xkb.compose_state_get_one_sym
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define _GLFW_DECORATION_WIDTH 4
|
#define _GLFW_DECORATION_WIDTH 4
|
||||||
#define _GLFW_DECORATION_TOP 24
|
#define _GLFW_DECORATION_TOP 24
|
||||||
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
|
#define _GLFW_DECORATION_VERTICAL (_GLFW_DECORATION_TOP + _GLFW_DECORATION_WIDTH)
|
||||||
@@ -241,52 +203,15 @@ typedef struct _GLFWlibraryWayland
|
|||||||
|
|
||||||
int32_t keyboardRepeatRate;
|
int32_t keyboardRepeatRate;
|
||||||
int32_t keyboardRepeatDelay;
|
int32_t keyboardRepeatDelay;
|
||||||
int keyboardLastKey;
|
|
||||||
int keyboardLastScancode;
|
|
||||||
int timerfd;
|
|
||||||
short int keycodes[256];
|
|
||||||
short int scancodes[GLFW_KEY_LAST + 1];
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
void* handle;
|
long codepoint;
|
||||||
struct xkb_context* context;
|
int plain;
|
||||||
struct xkb_keymap* keymap;
|
int glfwKeyCode;
|
||||||
struct xkb_state* state;
|
int scancode;
|
||||||
|
double nextRepeatAt;
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
_GLFWwindow* keyboardFocus;
|
||||||
struct xkb_compose_state* composeState;
|
} keyRepeatInfo;
|
||||||
#endif
|
_GLFWXKBData xkb;
|
||||||
|
|
||||||
xkb_mod_mask_t controlMask;
|
|
||||||
xkb_mod_mask_t altMask;
|
|
||||||
xkb_mod_mask_t shiftMask;
|
|
||||||
xkb_mod_mask_t superMask;
|
|
||||||
xkb_mod_mask_t capsLockMask;
|
|
||||||
xkb_mod_mask_t numLockMask;
|
|
||||||
unsigned int modifiers;
|
|
||||||
|
|
||||||
PFN_xkb_context_new context_new;
|
|
||||||
PFN_xkb_context_unref context_unref;
|
|
||||||
PFN_xkb_keymap_new_from_string keymap_new_from_string;
|
|
||||||
PFN_xkb_keymap_unref keymap_unref;
|
|
||||||
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
|
||||||
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
|
||||||
PFN_xkb_state_new state_new;
|
|
||||||
PFN_xkb_state_unref state_unref;
|
|
||||||
PFN_xkb_state_key_get_syms state_key_get_syms;
|
|
||||||
PFN_xkb_state_update_mask state_update_mask;
|
|
||||||
PFN_xkb_state_serialize_mods state_serialize_mods;
|
|
||||||
|
|
||||||
#ifdef HAVE_XKBCOMMON_COMPOSE_H
|
|
||||||
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
|
||||||
PFN_xkb_compose_table_unref compose_table_unref;
|
|
||||||
PFN_xkb_compose_state_new compose_state_new;
|
|
||||||
PFN_xkb_compose_state_unref compose_state_unref;
|
|
||||||
PFN_xkb_compose_state_feed compose_state_feed;
|
|
||||||
PFN_xkb_compose_state_get_status compose_state_get_status;
|
|
||||||
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
|
||||||
#endif
|
|
||||||
} xkb;
|
|
||||||
|
|
||||||
_GLFWwindow* pointerFocus;
|
_GLFWwindow* pointerFocus;
|
||||||
_GLFWwindow* keyboardFocus;
|
_GLFWwindow* keyboardFocus;
|
||||||
@@ -336,4 +261,3 @@ typedef struct _GLFWcursorWayland
|
|||||||
|
|
||||||
|
|
||||||
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
void _glfwAddOutputWayland(uint32_t name, uint32_t version);
|
||||||
|
|
||||||
|
|||||||
65
glfw/wl_window.c
vendored
65
glfw/wl_window.c
vendored
@@ -35,7 +35,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/mman.h>
|
#include <sys/mman.h>
|
||||||
#include <sys/timerfd.h>
|
|
||||||
#include <poll.h>
|
#include <poll.h>
|
||||||
|
|
||||||
|
|
||||||
@@ -690,16 +689,34 @@ static GLFWbool createXdgSurface(_GLFWwindow* window)
|
|||||||
return GLFW_TRUE;
|
return GLFW_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
dispatchPendingKeyRepeats() {
|
||||||
|
if (_glfw.wl.keyRepeatInfo.nextRepeatAt <= 0 || _glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return;
|
||||||
|
double now = glfwGetTime();
|
||||||
|
const int mods = _glfw.wl.xkb.modifiers;
|
||||||
|
while (_glfw.wl.keyRepeatInfo.nextRepeatAt <= now) {
|
||||||
|
_glfwInputKey(_glfw.wl.keyRepeatInfo.keyboardFocus, _glfw.wl.keyRepeatInfo.glfwKeyCode, _glfw.wl.keyRepeatInfo.scancode, GLFW_REPEAT, mods);
|
||||||
|
if (_glfw.wl.keyRepeatInfo.codepoint > -1) _glfwInputChar(_glfw.wl.keyRepeatInfo.keyboardFocus, _glfw.wl.keyRepeatInfo.codepoint, mods, _glfw.wl.keyRepeatInfo.plain);
|
||||||
|
_glfw.wl.keyRepeatInfo.nextRepeatAt += 1.0 / _glfw.wl.keyboardRepeatRate;
|
||||||
|
now = glfwGetTime();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
adjustTimeoutForKeyRepeat(int timeout) {
|
||||||
|
if (_glfw.wl.keyRepeatInfo.nextRepeatAt <= 0 || _glfw.wl.keyRepeatInfo.keyboardFocus != _glfw.wl.keyboardFocus || _glfw.wl.keyboardRepeatRate == 0) return timeout;
|
||||||
|
double now = glfwGetTime();
|
||||||
|
if (timeout < 0 || now + timeout / 1000. > _glfw.wl.keyRepeatInfo.nextRepeatAt) {
|
||||||
|
timeout = _glfw.wl.keyRepeatInfo.nextRepeatAt <= now ? 0 : ( (_glfw.wl.keyRepeatInfo.nextRepeatAt - now) * 1000 + 1 );
|
||||||
|
}
|
||||||
|
return timeout;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
handleEvents(int timeout)
|
handleEvents(int timeout)
|
||||||
{
|
{
|
||||||
struct wl_display* display = _glfw.wl.display;
|
struct wl_display* display = _glfw.wl.display;
|
||||||
struct pollfd fds[] = {
|
struct pollfd pfd = { wl_display_get_fd(display), POLLIN };
|
||||||
{ wl_display_get_fd(display), POLLIN },
|
|
||||||
{ _glfw.wl.timerfd, POLLIN },
|
|
||||||
};
|
|
||||||
ssize_t read_ret;
|
|
||||||
uint64_t repeats, i;
|
|
||||||
|
|
||||||
while (wl_display_prepare_read(display) != 0)
|
while (wl_display_prepare_read(display) != 0)
|
||||||
wl_display_dispatch_pending(display);
|
wl_display_dispatch_pending(display);
|
||||||
@@ -719,9 +736,12 @@ handleEvents(int timeout)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (poll(fds, 2, timeout) > 0)
|
dispatchPendingKeyRepeats();
|
||||||
|
timeout = adjustTimeoutForKeyRepeat(timeout);
|
||||||
|
|
||||||
|
if (poll(&pfd, 1, timeout) > 0)
|
||||||
{
|
{
|
||||||
if (fds[0].revents & POLLIN)
|
if (pfd.revents & POLLIN)
|
||||||
{
|
{
|
||||||
wl_display_read_events(display);
|
wl_display_read_events(display);
|
||||||
wl_display_dispatch_pending(display);
|
wl_display_dispatch_pending(display);
|
||||||
@@ -731,22 +751,12 @@ handleEvents(int timeout)
|
|||||||
wl_display_cancel_read(display);
|
wl_display_cancel_read(display);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fds[1].revents & POLLIN)
|
|
||||||
{
|
|
||||||
read_ret = read(_glfw.wl.timerfd, &repeats, sizeof(repeats));
|
|
||||||
if (read_ret != 8)
|
|
||||||
return;
|
|
||||||
|
|
||||||
for (i = 0; i < repeats; ++i)
|
|
||||||
_glfwInputKey(_glfw.wl.keyboardFocus, _glfw.wl.keyboardLastKey,
|
|
||||||
_glfw.wl.keyboardLastScancode, GLFW_REPEAT,
|
|
||||||
_glfw.wl.xkb.modifiers);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wl_display_cancel_read(display);
|
wl_display_cancel_read(display);
|
||||||
}
|
}
|
||||||
|
dispatchPendingKeyRepeats();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Translates a GLFW standard cursor to a theme cursor name
|
// Translates a GLFW standard cursor to a theme cursor name
|
||||||
@@ -1079,11 +1089,15 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
"Wayland: Window attention request not implemented yet");
|
"Wayland: Window attention request not implemented yet");
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window, int64_t param)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
// TODO
|
// TODO: Use an actual Wayland API to implement this when one becomes available
|
||||||
_glfwInputError(GLFW_PLATFORM_ERROR,
|
int fd = open("/dev/tty", O_WRONLY | O_CLOEXEC);
|
||||||
"Wayland: Window bell request not implemented yet");
|
if (fd > -1) {
|
||||||
|
int ret = write(fd, "\x07", 1) == 1 ? GLFW_TRUE : GLFW_FALSE;
|
||||||
|
close(fd);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
return GLFW_FALSE;
|
return GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1236,7 +1250,7 @@ const char* _glfwPlatformGetScancodeName(int scancode)
|
|||||||
|
|
||||||
int _glfwPlatformGetKeyScancode(int key)
|
int _glfwPlatformGetKeyScancode(int key)
|
||||||
{
|
{
|
||||||
return _glfw.wl.scancodes[key];
|
return _glfw.wl.xkb.scancodes[key];
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
int _glfwPlatformCreateCursor(_GLFWcursor* cursor,
|
||||||
@@ -1547,4 +1561,3 @@ GLFWAPI struct wl_surface* glfwGetWaylandWindow(GLFWwindow* handle)
|
|||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return window->wl.surface;
|
return window->wl.surface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
5
glfw/x11_window.c
vendored
5
glfw/x11_window.c
vendored
@@ -2340,9 +2340,9 @@ void _glfwPlatformRequestWindowAttention(_GLFWwindow* window)
|
|||||||
0, 1, 0);
|
0, 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
int _glfwPlatformWindowBell(_GLFWwindow* window, int64_t param)
|
int _glfwPlatformWindowBell(_GLFWwindow* window)
|
||||||
{
|
{
|
||||||
return XkbBell(_glfw.x11.display, window->x11.handle, (int)param, (Atom)0) ? GLFW_TRUE : GLFW_FALSE;
|
return XkbBell(_glfw.x11.display, window->x11.handle, 100, (Atom)0) ? GLFW_TRUE : GLFW_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
void _glfwPlatformFocusWindow(_GLFWwindow* window)
|
||||||
@@ -3044,4 +3044,3 @@ GLFWAPI const char* glfwGetX11SelectionString(void)
|
|||||||
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
_GLFW_REQUIRE_INIT_OR_RETURN(NULL);
|
||||||
return getSelectionString(_glfw.x11.PRIMARY);
|
return getSelectionString(_glfw.x11.PRIMARY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
374
glfw/xkb_glfw.h
vendored
Normal file
374
glfw/xkb_glfw.h
vendored
Normal file
@@ -0,0 +1,374 @@
|
|||||||
|
//========================================================================
|
||||||
|
// GLFW 3.3 XKB - www.glfw.org
|
||||||
|
//------------------------------------------------------------------------
|
||||||
|
// Copyright (c) 2014 Kovid Goyal <kovid@kovidgoyal.net>
|
||||||
|
//
|
||||||
|
// 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.
|
||||||
|
//
|
||||||
|
//========================================================================
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <xkbcommon/xkbcommon.h>
|
||||||
|
#include <xkbcommon/xkbcommon-compose.h>
|
||||||
|
|
||||||
|
typedef struct xkb_context* (* PFN_xkb_context_new)(enum xkb_context_flags);
|
||||||
|
typedef void (* PFN_xkb_context_unref)(struct xkb_context*);
|
||||||
|
typedef struct xkb_keymap* (* PFN_xkb_keymap_new_from_string)(struct xkb_context*, const char*, enum xkb_keymap_format, enum xkb_keymap_compile_flags);
|
||||||
|
typedef void (* PFN_xkb_keymap_unref)(struct xkb_keymap*);
|
||||||
|
typedef xkb_mod_index_t (* PFN_xkb_keymap_mod_get_index)(struct xkb_keymap*, const char*);
|
||||||
|
typedef int (* PFN_xkb_keymap_key_repeats)(struct xkb_keymap*, xkb_keycode_t);
|
||||||
|
typedef struct xkb_state* (* PFN_xkb_state_new)(struct xkb_keymap*);
|
||||||
|
typedef void (* PFN_xkb_state_unref)(struct xkb_state*);
|
||||||
|
typedef int (* PFN_xkb_state_key_get_syms)(struct xkb_state*, xkb_keycode_t, const xkb_keysym_t**);
|
||||||
|
typedef enum xkb_state_component (* PFN_xkb_state_update_mask)(struct xkb_state*, xkb_mod_mask_t, xkb_mod_mask_t, xkb_mod_mask_t, xkb_layout_index_t, xkb_layout_index_t, xkb_layout_index_t);
|
||||||
|
typedef xkb_mod_mask_t (* PFN_xkb_state_serialize_mods)(struct xkb_state*, enum xkb_state_component);
|
||||||
|
|
||||||
|
#define xkb_context_new GLFW_XKB_GLOBAL_NAME.context_new
|
||||||
|
#define xkb_context_unref GLFW_XKB_GLOBAL_NAME.context_unref
|
||||||
|
#define xkb_keymap_new_from_string GLFW_XKB_GLOBAL_NAME.keymap_new_from_string
|
||||||
|
#define xkb_keymap_unref GLFW_XKB_GLOBAL_NAME.keymap_unref
|
||||||
|
#define xkb_keymap_mod_get_index GLFW_XKB_GLOBAL_NAME.keymap_mod_get_index
|
||||||
|
#define xkb_keymap_key_repeats GLFW_XKB_GLOBAL_NAME.keymap_key_repeats
|
||||||
|
#define xkb_state_new GLFW_XKB_GLOBAL_NAME.state_new
|
||||||
|
#define xkb_state_unref GLFW_XKB_GLOBAL_NAME.state_unref
|
||||||
|
#define xkb_state_key_get_syms GLFW_XKB_GLOBAL_NAME.state_key_get_syms
|
||||||
|
#define xkb_state_update_mask GLFW_XKB_GLOBAL_NAME.state_update_mask
|
||||||
|
#define xkb_state_serialize_mods GLFW_XKB_GLOBAL_NAME.state_serialize_mods
|
||||||
|
|
||||||
|
typedef struct xkb_compose_table* (* PFN_xkb_compose_table_new_from_locale)(struct xkb_context*, const char*, enum xkb_compose_compile_flags);
|
||||||
|
typedef void (* PFN_xkb_compose_table_unref)(struct xkb_compose_table*);
|
||||||
|
typedef struct xkb_compose_state* (* PFN_xkb_compose_state_new)(struct xkb_compose_table*, enum xkb_compose_state_flags);
|
||||||
|
typedef void (* PFN_xkb_compose_state_unref)(struct xkb_compose_state*);
|
||||||
|
typedef enum xkb_compose_feed_result (* PFN_xkb_compose_state_feed)(struct xkb_compose_state*, xkb_keysym_t);
|
||||||
|
typedef enum xkb_compose_status (* PFN_xkb_compose_state_get_status)(struct xkb_compose_state*);
|
||||||
|
typedef xkb_keysym_t (* PFN_xkb_compose_state_get_one_sym)(struct xkb_compose_state*);
|
||||||
|
|
||||||
|
#define xkb_compose_table_new_from_locale GLFW_XKB_GLOBAL_NAME.compose_table_new_from_locale
|
||||||
|
#define xkb_compose_table_unref GLFW_XKB_GLOBAL_NAME.compose_table_unref
|
||||||
|
#define xkb_compose_state_new GLFW_XKB_GLOBAL_NAME.compose_state_new
|
||||||
|
#define xkb_compose_state_unref GLFW_XKB_GLOBAL_NAME.compose_state_unref
|
||||||
|
#define xkb_compose_state_feed GLFW_XKB_GLOBAL_NAME.compose_state_feed
|
||||||
|
#define xkb_compose_state_get_status GLFW_XKB_GLOBAL_NAME.compose_state_get_status
|
||||||
|
#define xkb_compose_state_get_one_sym GLFW_XKB_GLOBAL_NAME.compose_state_get_one_sym
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
void* handle;
|
||||||
|
struct xkb_context* context;
|
||||||
|
struct xkb_keymap* keymap;
|
||||||
|
struct xkb_state* state;
|
||||||
|
struct xkb_compose_state* composeState;
|
||||||
|
short int keycodes[256];
|
||||||
|
short int scancodes[GLFW_KEY_LAST + 1];
|
||||||
|
|
||||||
|
xkb_mod_mask_t controlMask;
|
||||||
|
xkb_mod_mask_t altMask;
|
||||||
|
xkb_mod_mask_t shiftMask;
|
||||||
|
xkb_mod_mask_t superMask;
|
||||||
|
xkb_mod_mask_t capsLockMask;
|
||||||
|
xkb_mod_mask_t numLockMask;
|
||||||
|
unsigned int modifiers;
|
||||||
|
|
||||||
|
PFN_xkb_context_new context_new;
|
||||||
|
PFN_xkb_context_unref context_unref;
|
||||||
|
PFN_xkb_keymap_new_from_string keymap_new_from_string;
|
||||||
|
PFN_xkb_keymap_unref keymap_unref;
|
||||||
|
PFN_xkb_keymap_mod_get_index keymap_mod_get_index;
|
||||||
|
PFN_xkb_keymap_key_repeats keymap_key_repeats;
|
||||||
|
PFN_xkb_state_new state_new;
|
||||||
|
PFN_xkb_state_unref state_unref;
|
||||||
|
PFN_xkb_state_key_get_syms state_key_get_syms;
|
||||||
|
PFN_xkb_state_update_mask state_update_mask;
|
||||||
|
PFN_xkb_state_serialize_mods state_serialize_mods;
|
||||||
|
|
||||||
|
PFN_xkb_compose_table_new_from_locale compose_table_new_from_locale;
|
||||||
|
PFN_xkb_compose_table_unref compose_table_unref;
|
||||||
|
PFN_xkb_compose_state_new compose_state_new;
|
||||||
|
PFN_xkb_compose_state_unref compose_state_unref;
|
||||||
|
PFN_xkb_compose_state_feed compose_state_feed;
|
||||||
|
PFN_xkb_compose_state_get_status compose_state_get_status;
|
||||||
|
PFN_xkb_compose_state_get_one_sym compose_state_get_one_sym;
|
||||||
|
} _GLFWXKBData;
|
||||||
|
|
||||||
|
#define bind_xkb_sym(name) GLFW_XKB_GLOBAL_NAME.name = (PFN_xkb_##name) _glfw_dlsym(GLFW_XKB_GLOBAL_NAME.handle, "xkb_" #name)
|
||||||
|
#define load_glfw_xkb() {\
|
||||||
|
GLFW_XKB_GLOBAL_NAME.handle = _glfw_dlopen("libxkbcommon.so.0"); \
|
||||||
|
if (!GLFW_XKB_GLOBAL_NAME.handle) \
|
||||||
|
{ \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, \
|
||||||
|
"Failed to open libxkbcommon"); \
|
||||||
|
return GLFW_FALSE; \
|
||||||
|
} \
|
||||||
|
bind_xkb_sym(context_new); \
|
||||||
|
bind_xkb_sym(context_unref); \
|
||||||
|
bind_xkb_sym(keymap_new_from_string); \
|
||||||
|
bind_xkb_sym(keymap_unref); \
|
||||||
|
bind_xkb_sym(keymap_mod_get_index); \
|
||||||
|
bind_xkb_sym(keymap_key_repeats); \
|
||||||
|
bind_xkb_sym(state_new); \
|
||||||
|
bind_xkb_sym(state_unref); \
|
||||||
|
bind_xkb_sym(state_key_get_syms); \
|
||||||
|
bind_xkb_sym(state_update_mask); \
|
||||||
|
bind_xkb_sym(state_serialize_mods); \
|
||||||
|
bind_xkb_sym(compose_table_new_from_locale); \
|
||||||
|
bind_xkb_sym(compose_table_unref); \
|
||||||
|
bind_xkb_sym(compose_state_new); \
|
||||||
|
bind_xkb_sym(compose_state_unref); \
|
||||||
|
bind_xkb_sym(compose_state_feed); \
|
||||||
|
bind_xkb_sym(compose_state_get_status); \
|
||||||
|
bind_xkb_sym(compose_state_get_one_sym); \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define release_glfw_xkb() {\
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.composeState) { \
|
||||||
|
xkb_compose_state_unref(GLFW_XKB_GLOBAL_NAME.composeState); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.composeState = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keymap) { \
|
||||||
|
xkb_keymap_unref(GLFW_XKB_GLOBAL_NAME.keymap); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keymap = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.state) { \
|
||||||
|
xkb_state_unref(GLFW_XKB_GLOBAL_NAME.state); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.state = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.context) { \
|
||||||
|
xkb_context_unref(GLFW_XKB_GLOBAL_NAME.context); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.context = NULL; \
|
||||||
|
} \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.handle) { \
|
||||||
|
_glfw_dlclose(GLFW_XKB_GLOBAL_NAME.handle); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.handle = NULL; \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define create_glfw_xkb_context() {\
|
||||||
|
GLFW_XKB_GLOBAL_NAME.context = xkb_context_new(0); \
|
||||||
|
if (!GLFW_XKB_GLOBAL_NAME.context) \
|
||||||
|
{ \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, \
|
||||||
|
"Failed to initialize XKB context"); \
|
||||||
|
return GLFW_FALSE; \
|
||||||
|
} \
|
||||||
|
int scancode; \
|
||||||
|
memset(GLFW_XKB_GLOBAL_NAME.keycodes, -1, sizeof(GLFW_XKB_GLOBAL_NAME.keycodes)); \
|
||||||
|
memset(GLFW_XKB_GLOBAL_NAME.scancodes, -1, sizeof(GLFW_XKB_GLOBAL_NAME.scancodes)); \
|
||||||
|
\
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_GRAVE] = GLFW_KEY_GRAVE_ACCENT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_1] = GLFW_KEY_1; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_2] = GLFW_KEY_2; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_3] = GLFW_KEY_3; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_4] = GLFW_KEY_4; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_5] = GLFW_KEY_5; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_6] = GLFW_KEY_6; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_7] = GLFW_KEY_7; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_8] = GLFW_KEY_8; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_9] = GLFW_KEY_9; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_0] = GLFW_KEY_0; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SPACE] = GLFW_KEY_SPACE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_MINUS] = GLFW_KEY_MINUS; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_EQUAL] = GLFW_KEY_EQUAL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_Q] = GLFW_KEY_Q; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_W] = GLFW_KEY_W; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_E] = GLFW_KEY_E; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_R] = GLFW_KEY_R; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_T] = GLFW_KEY_T; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_Y] = GLFW_KEY_Y; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_U] = GLFW_KEY_U; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_I] = GLFW_KEY_I; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_O] = GLFW_KEY_O; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_P] = GLFW_KEY_P; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTBRACE] = GLFW_KEY_LEFT_BRACKET; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTBRACE] = GLFW_KEY_RIGHT_BRACKET; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_A] = GLFW_KEY_A; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_S] = GLFW_KEY_S; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_D] = GLFW_KEY_D; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F] = GLFW_KEY_F; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_G] = GLFW_KEY_G; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_H] = GLFW_KEY_H; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_J] = GLFW_KEY_J; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_K] = GLFW_KEY_K; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_L] = GLFW_KEY_L; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SEMICOLON] = GLFW_KEY_SEMICOLON; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_APOSTROPHE] = GLFW_KEY_APOSTROPHE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_Z] = GLFW_KEY_Z; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_X] = GLFW_KEY_X; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_C] = GLFW_KEY_C; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_V] = GLFW_KEY_V; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_B] = GLFW_KEY_B; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_N] = GLFW_KEY_N; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_M] = GLFW_KEY_M; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_COMMA] = GLFW_KEY_COMMA; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_DOT] = GLFW_KEY_PERIOD; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SLASH] = GLFW_KEY_SLASH; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_BACKSLASH] = GLFW_KEY_BACKSLASH; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_ESC] = GLFW_KEY_ESCAPE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_TAB] = GLFW_KEY_TAB; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTSHIFT] = GLFW_KEY_LEFT_SHIFT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTSHIFT] = GLFW_KEY_RIGHT_SHIFT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTCTRL] = GLFW_KEY_LEFT_CONTROL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTCTRL] = GLFW_KEY_RIGHT_CONTROL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTALT] = GLFW_KEY_LEFT_ALT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTALT] = GLFW_KEY_RIGHT_ALT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFTMETA] = GLFW_KEY_LEFT_SUPER; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHTMETA] = GLFW_KEY_RIGHT_SUPER; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_MENU] = GLFW_KEY_MENU; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_NUMLOCK] = GLFW_KEY_NUM_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_CAPSLOCK] = GLFW_KEY_CAPS_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PRINT] = GLFW_KEY_PRINT_SCREEN; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_SCROLLLOCK] = GLFW_KEY_SCROLL_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PAUSE] = GLFW_KEY_PAUSE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_DELETE] = GLFW_KEY_DELETE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_BACKSPACE] = GLFW_KEY_BACKSPACE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_ENTER] = GLFW_KEY_ENTER; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_HOME] = GLFW_KEY_HOME; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_END] = GLFW_KEY_END; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PAGEUP] = GLFW_KEY_PAGE_UP; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_PAGEDOWN] = GLFW_KEY_PAGE_DOWN; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_INSERT] = GLFW_KEY_INSERT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_LEFT] = GLFW_KEY_LEFT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_RIGHT] = GLFW_KEY_RIGHT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_DOWN] = GLFW_KEY_DOWN; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_UP] = GLFW_KEY_UP; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F1] = GLFW_KEY_F1; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F2] = GLFW_KEY_F2; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F3] = GLFW_KEY_F3; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F4] = GLFW_KEY_F4; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F5] = GLFW_KEY_F5; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F6] = GLFW_KEY_F6; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F7] = GLFW_KEY_F7; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F8] = GLFW_KEY_F8; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F9] = GLFW_KEY_F9; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F10] = GLFW_KEY_F10; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F11] = GLFW_KEY_F11; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F12] = GLFW_KEY_F12; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F13] = GLFW_KEY_F13; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F14] = GLFW_KEY_F14; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F15] = GLFW_KEY_F15; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F16] = GLFW_KEY_F16; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F17] = GLFW_KEY_F17; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F18] = GLFW_KEY_F18; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F19] = GLFW_KEY_F19; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F20] = GLFW_KEY_F20; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F21] = GLFW_KEY_F21; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F22] = GLFW_KEY_F22; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F23] = GLFW_KEY_F23; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_F24] = GLFW_KEY_F24; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPSLASH] = GLFW_KEY_KP_DIVIDE; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPDOT] = GLFW_KEY_KP_MULTIPLY; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPMINUS] = GLFW_KEY_KP_SUBTRACT; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPPLUS] = GLFW_KEY_KP_ADD; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP0] = GLFW_KEY_KP_0; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP1] = GLFW_KEY_KP_1; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP2] = GLFW_KEY_KP_2; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP3] = GLFW_KEY_KP_3; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP4] = GLFW_KEY_KP_4; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP5] = GLFW_KEY_KP_5; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP6] = GLFW_KEY_KP_6; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP7] = GLFW_KEY_KP_7; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP8] = GLFW_KEY_KP_8; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KP9] = GLFW_KEY_KP_9; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPCOMMA] = GLFW_KEY_KP_DECIMAL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPEQUAL] = GLFW_KEY_KP_EQUAL; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keycodes[KEY_KPENTER] = GLFW_KEY_KP_ENTER; \
|
||||||
|
\
|
||||||
|
for (scancode = 0; scancode < 256; scancode++) \
|
||||||
|
{ \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keycodes[scancode] > 0) \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.scancodes[GLFW_XKB_GLOBAL_NAME.keycodes[scancode]] = scancode; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define xkb_glfw_compile_keymap(map_str) { \
|
||||||
|
const char* locale = NULL; \
|
||||||
|
struct xkb_state* state = NULL; \
|
||||||
|
struct xkb_keymap* keymap = NULL; \
|
||||||
|
struct xkb_compose_table* compose_table = NULL; \
|
||||||
|
struct xkb_compose_state* compose_state = NULL; \
|
||||||
|
\
|
||||||
|
keymap = xkb_keymap_new_from_string(GLFW_XKB_GLOBAL_NAME.context, map_str, XKB_KEYMAP_FORMAT_TEXT_V1, 0); \
|
||||||
|
if (!keymap) _glfwInputError(GLFW_PLATFORM_ERROR, "Failed to compile XKB keymap"); \
|
||||||
|
else { \
|
||||||
|
state = xkb_state_new(keymap); \
|
||||||
|
if (!state) { \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB state"); \
|
||||||
|
xkb_keymap_unref(keymap); keymap = NULL; \
|
||||||
|
} else { \
|
||||||
|
/* Look up the preferred locale, falling back to "C" as default. */ \
|
||||||
|
locale = getenv("LC_ALL"); \
|
||||||
|
if (!locale) locale = getenv("LC_CTYPE"); \
|
||||||
|
if (!locale) locale = getenv("LANG"); \
|
||||||
|
if (!locale) locale = "C"; \
|
||||||
|
compose_table = xkb_compose_table_new_from_locale(GLFW_XKB_GLOBAL_NAME.context, locale, XKB_COMPOSE_COMPILE_NO_FLAGS); \
|
||||||
|
if (!compose_table) { \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose table"); \
|
||||||
|
xkb_keymap_unref(keymap); keymap = NULL; \
|
||||||
|
xkb_state_unref(state); state = NULL; \
|
||||||
|
} else { \
|
||||||
|
compose_state = xkb_compose_state_new(compose_table, XKB_COMPOSE_STATE_NO_FLAGS); \
|
||||||
|
xkb_compose_table_unref(compose_table); compose_table = NULL; \
|
||||||
|
if (!compose_state) { \
|
||||||
|
_glfwInputError(GLFW_PLATFORM_ERROR, "Failed to create XKB compose state"); \
|
||||||
|
xkb_keymap_unref(keymap); keymap = NULL; \
|
||||||
|
xkb_state_unref(state); state = NULL; \
|
||||||
|
}\
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
if (keymap && state && compose_state) { \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.composeState) xkb_compose_state_unref(GLFW_XKB_GLOBAL_NAME.composeState); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.composeState = compose_state; \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keymap) xkb_keymap_unref(GLFW_XKB_GLOBAL_NAME.keymap); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.keymap = keymap; \
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.state) xkb_state_unref(GLFW_XKB_GLOBAL_NAME.state); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.state = state; \
|
||||||
|
}\
|
||||||
|
if (GLFW_XKB_GLOBAL_NAME.keymap) { \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.controlMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Control"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.altMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Mod1"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.shiftMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Shift"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.superMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Mod4"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.capsLockMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Lock"); \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.numLockMask = 1 << xkb_keymap_mod_get_index(GLFW_XKB_GLOBAL_NAME.keymap, "Mod2"); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define xkb_glfw_update_modifiers(depressed, latched, locked, group) {\
|
||||||
|
xkb_mod_mask_t mask; \
|
||||||
|
unsigned int modifiers = 0; \
|
||||||
|
if (!GLFW_XKB_GLOBAL_NAME.keymap) return; \
|
||||||
|
xkb_state_update_mask(GLFW_XKB_GLOBAL_NAME.state, depressed, latched, locked, 0, 0, group); \
|
||||||
|
mask = xkb_state_serialize_mods(GLFW_XKB_GLOBAL_NAME.state, XKB_STATE_MODS_DEPRESSED | XKB_STATE_LAYOUT_DEPRESSED | XKB_STATE_MODS_LATCHED | XKB_STATE_LAYOUT_LATCHED); \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.controlMask) modifiers |= GLFW_MOD_CONTROL; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.altMask) modifiers |= GLFW_MOD_ALT; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.shiftMask) modifiers |= GLFW_MOD_SHIFT; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.superMask) modifiers |= GLFW_MOD_SUPER; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.capsLockMask) modifiers |= GLFW_MOD_CAPS_LOCK; \
|
||||||
|
if (mask & GLFW_XKB_GLOBAL_NAME.numLockMask) modifiers |= GLFW_MOD_NUM_LOCK; \
|
||||||
|
GLFW_XKB_GLOBAL_NAME.modifiers = modifiers; \
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#define xkb_glfw_to_glfw_key_code(key) \
|
||||||
|
((key < sizeof(GLFW_XKB_GLOBAL_NAME.keycodes) / sizeof(GLFW_XKB_GLOBAL_NAME.keycodes[0])) ? GLFW_XKB_GLOBAL_NAME.keycodes[key] : GLFW_KEY_UNKNOWN)
|
||||||
0
kittens/ask/__init__.py
Normal file
0
kittens/ask/__init__.py
Normal file
114
kittens/ask/main.py
Normal file
114
kittens/ask/main.py
Normal file
@@ -0,0 +1,114 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
# vim:fileencoding=utf-8
|
||||||
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import json
|
||||||
|
import os
|
||||||
|
import readline
|
||||||
|
import sys
|
||||||
|
|
||||||
|
from kitty.cli import parse_args
|
||||||
|
from kitty.constants import cache_dir
|
||||||
|
|
||||||
|
from ..tui.operations import alternate_screen, styled
|
||||||
|
|
||||||
|
|
||||||
|
def get_history_items():
|
||||||
|
return list(map(readline.get_history_item, range(1, readline.get_current_history_length() + 1)))
|
||||||
|
|
||||||
|
|
||||||
|
def sort_key(item):
|
||||||
|
return len(item), item.lower()
|
||||||
|
|
||||||
|
|
||||||
|
class HistoryCompleter:
|
||||||
|
|
||||||
|
def __init__(self, name=None):
|
||||||
|
self.matches = []
|
||||||
|
self.history_path = None
|
||||||
|
if name:
|
||||||
|
ddir = os.path.join(cache_dir(), 'ask')
|
||||||
|
try:
|
||||||
|
os.makedirs(ddir)
|
||||||
|
except FileExistsError:
|
||||||
|
pass
|
||||||
|
self.history_path = os.path.join(ddir, name)
|
||||||
|
|
||||||
|
def complete(self, text, state):
|
||||||
|
response = None
|
||||||
|
if state == 0:
|
||||||
|
history_values = get_history_items()
|
||||||
|
if text:
|
||||||
|
self.matches = sorted(
|
||||||
|
(h for h in history_values if h and h.startswith(text)), key=sort_key)
|
||||||
|
else:
|
||||||
|
self.matches = []
|
||||||
|
try:
|
||||||
|
response = self.matches[state]
|
||||||
|
except IndexError:
|
||||||
|
response = None
|
||||||
|
return response
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
if self.history_path:
|
||||||
|
if os.path.exists(self.history_path):
|
||||||
|
readline.read_history_file(self.history_path)
|
||||||
|
readline.set_completer(self.complete)
|
||||||
|
readline.parse_and_bind('tab: complete')
|
||||||
|
return self
|
||||||
|
|
||||||
|
def __exit__(self, *a):
|
||||||
|
if self.history_path:
|
||||||
|
readline.write_history_file(self.history_path)
|
||||||
|
|
||||||
|
|
||||||
|
def option_text():
|
||||||
|
return '''\
|
||||||
|
--type -t
|
||||||
|
choices=line
|
||||||
|
default=line
|
||||||
|
Type of input. Defaults to asking for a line of text.
|
||||||
|
|
||||||
|
|
||||||
|
--message -m
|
||||||
|
The message to display to the user. If not specified a default
|
||||||
|
message is shown.
|
||||||
|
|
||||||
|
|
||||||
|
--name -n
|
||||||
|
The name for this question. Used to store history of previous answers which can
|
||||||
|
be used for completions and via the browse history readline bindings.
|
||||||
|
'''
|
||||||
|
|
||||||
|
|
||||||
|
def real_main(args):
|
||||||
|
msg = 'Ask the user for input'
|
||||||
|
try:
|
||||||
|
args, items = parse_args(args[1:], option_text, '', msg, 'kitty ask')
|
||||||
|
except SystemExit as e:
|
||||||
|
print(e.args[0])
|
||||||
|
input('Press enter to quit...')
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
readline.read_init_file()
|
||||||
|
|
||||||
|
with alternate_screen(), HistoryCompleter(args.name):
|
||||||
|
if args.message:
|
||||||
|
print(styled(args.message, bold=True))
|
||||||
|
|
||||||
|
prompt = '> '
|
||||||
|
try:
|
||||||
|
ans = input(prompt)
|
||||||
|
except (KeyboardInterrupt, EOFError):
|
||||||
|
return
|
||||||
|
print('OK:', json.dumps(ans))
|
||||||
|
|
||||||
|
|
||||||
|
def main(args=sys.argv):
|
||||||
|
try:
|
||||||
|
real_main(args)
|
||||||
|
except Exception as e:
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc(file=sys.stdout)
|
||||||
|
input('Press enter to quit...')
|
||||||
|
raise SystemExit(1)
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import sys
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
|
||||||
from kitty.terminfo import string_capabilities
|
from kitty.terminfo import string_capabilities
|
||||||
@@ -151,3 +152,11 @@ def cursor(write):
|
|||||||
write(SAVE_CURSOR)
|
write(SAVE_CURSOR)
|
||||||
yield
|
yield
|
||||||
write(RESTORE_CURSOR)
|
write(RESTORE_CURSOR)
|
||||||
|
|
||||||
|
|
||||||
|
@contextmanager
|
||||||
|
def alternate_screen(f=None):
|
||||||
|
f = f or sys.stdout
|
||||||
|
print(set_mode('ALTERNATE_SCREEN'), end='', file=f)
|
||||||
|
yield
|
||||||
|
print(reset_mode('ALTERNATE_SCREEN'), end='', file=f)
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ expression instead.
|
|||||||
|
|
||||||
--url-prefixes
|
--url-prefixes
|
||||||
default={0}
|
default={0}
|
||||||
Comma separeted list of recognized URL prefixes. Defaults to:
|
Comma separated list of recognized URL prefixes. Defaults to:
|
||||||
{0}
|
{0}
|
||||||
'''.format, ','.join(sorted(URL_PREFIXES)))
|
'''.format, ','.join(sorted(URL_PREFIXES)))
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
import atexit
|
import atexit
|
||||||
|
import json
|
||||||
import re
|
import re
|
||||||
import socket
|
import socket
|
||||||
from functools import partial
|
from functools import partial
|
||||||
@@ -204,7 +205,6 @@ class Boss:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
def peer_message_received(self, msg):
|
def peer_message_received(self, msg):
|
||||||
import json
|
|
||||||
msg = msg.decode('utf-8')
|
msg = msg.decode('utf-8')
|
||||||
cmd_prefix = '\x1bP@kitty-cmd'
|
cmd_prefix = '\x1bP@kitty-cmd'
|
||||||
if msg.startswith(cmd_prefix):
|
if msg.startswith(cmd_prefix):
|
||||||
@@ -435,10 +435,17 @@ class Boss:
|
|||||||
overlay_for=w.id))
|
overlay_for=w.id))
|
||||||
overlay_window.action_on_close = partial(self.send_unicode_character, w.id)
|
overlay_window.action_on_close = partial(self.send_unicode_character, w.id)
|
||||||
|
|
||||||
|
def get_output(self, source_window, num_lines=1):
|
||||||
|
output = ''
|
||||||
|
s = source_window.screen
|
||||||
|
for i in range(min(num_lines, s.lines)):
|
||||||
|
output += str(s.linebuf.line(i))
|
||||||
|
return output
|
||||||
|
|
||||||
def send_unicode_character(self, target_window_id, source_window):
|
def send_unicode_character(self, target_window_id, source_window):
|
||||||
w = self.window_id_map.get(target_window_id)
|
w = self.window_id_map.get(target_window_id)
|
||||||
if w is not None:
|
if w is not None:
|
||||||
output = str(source_window.screen.linebuf.line(0))
|
output = self.get_output(source_window)
|
||||||
if output.startswith('OK: '):
|
if output.startswith('OK: '):
|
||||||
try:
|
try:
|
||||||
text = chr(int(output.partition(' ')[2], 16))
|
text = chr(int(output.partition(' ')[2], 16))
|
||||||
@@ -448,6 +455,28 @@ class Boss:
|
|||||||
else:
|
else:
|
||||||
w.paste(text)
|
w.paste(text)
|
||||||
|
|
||||||
|
def set_tab_title(self):
|
||||||
|
w = self.active_window
|
||||||
|
tab = self.active_tab
|
||||||
|
if w is not None and tab is not None and w.overlay_for is None:
|
||||||
|
args = ['--name=tab-title', '--message', _('Enter the new title for this tab below.')]
|
||||||
|
overlay_window = tab.new_special_window(
|
||||||
|
SpecialWindow(
|
||||||
|
['kitty', '+runpy', 'from kittens.ask.main import main; main()'] + args,
|
||||||
|
overlay_for=w.id))
|
||||||
|
overlay_window.action_on_close = partial(self.do_set_tab_title, tab.id)
|
||||||
|
|
||||||
|
def do_set_tab_title(self, tab_id, source_window):
|
||||||
|
output = self.get_output(source_window)
|
||||||
|
if output.startswith('OK: '):
|
||||||
|
title = json.loads(output.partition(' ')[2].strip())
|
||||||
|
tm = self.active_tab_manager
|
||||||
|
if tm is not None and title:
|
||||||
|
for tab in tm.tabs:
|
||||||
|
if tab.id == tab_id:
|
||||||
|
tab.set_title(title)
|
||||||
|
break
|
||||||
|
|
||||||
def run_simple_kitten(self, type_of_input, kitten, *args):
|
def run_simple_kitten(self, type_of_input, kitten, *args):
|
||||||
import shlex
|
import shlex
|
||||||
w = self.active_window
|
w = self.active_window
|
||||||
|
|||||||
@@ -6,9 +6,7 @@
|
|||||||
layout(std140) uniform CellRenderData {
|
layout(std140) uniform CellRenderData {
|
||||||
float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity;
|
float xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity;
|
||||||
|
|
||||||
uint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, url_color, url_style;
|
uint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, url_color, url_style, inverted;
|
||||||
|
|
||||||
int color1, color2;
|
|
||||||
|
|
||||||
uint xnum, ynum, cursor_x, cursor_y, cursor_w;
|
uint xnum, ynum, cursor_x, cursor_y, cursor_w;
|
||||||
|
|
||||||
@@ -21,7 +19,7 @@ layout(location=1) in uvec4 sprite_coords;
|
|||||||
layout(location=2) in uint is_selected;
|
layout(location=2) in uint is_selected;
|
||||||
|
|
||||||
|
|
||||||
|
const int fg_index_map[] = int[3](0, 1, 0);
|
||||||
const uvec2 cell_pos_map[] = uvec2[4](
|
const uvec2 cell_pos_map[] = uvec2[4](
|
||||||
uvec2(1, 0), // right, top
|
uvec2(1, 0), // right, top
|
||||||
uvec2(1, 1), // right, bottom
|
uvec2(1, 1), // right, bottom
|
||||||
@@ -135,10 +133,10 @@ void main() {
|
|||||||
|
|
||||||
// set cell color indices {{{
|
// set cell color indices {{{
|
||||||
uvec2 default_colors = uvec2(default_fg, default_bg);
|
uvec2 default_colors = uvec2(default_fg, default_bg);
|
||||||
ivec2 color_indices = ivec2(color1, color2);
|
|
||||||
uint text_attrs = sprite_coords[3];
|
uint text_attrs = sprite_coords[3];
|
||||||
int fg_index = color_indices[(text_attrs >> 6) & REVERSE_MASK];
|
uint is_inverted = ((text_attrs >> 6) & REVERSE_MASK) + inverted;
|
||||||
int bg_index = color_indices[1 - fg_index];
|
int fg_index = fg_index_map[is_inverted];
|
||||||
|
int bg_index = 1 - fg_index;
|
||||||
float cursor = is_cursor(c, r);
|
float cursor = is_cursor(c, r);
|
||||||
vec3 bg = to_color(colors[bg_index], default_colors[bg_index]);
|
vec3 bg = to_color(colors[bg_index], default_colors[bg_index]);
|
||||||
// }}}
|
// }}}
|
||||||
|
|||||||
114
kitty/cli.py
114
kitty/cli.py
@@ -2,16 +2,16 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
import os
|
||||||
import re
|
import re
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
|
||||||
from .config import load_config
|
from .config import defaults, load_config
|
||||||
from .constants import appname, defconf, is_macos, str_version
|
from .constants import appname, defconf, is_macos, is_wayland, str_version
|
||||||
from .layout import all_layouts
|
from .layout import all_layouts
|
||||||
|
|
||||||
is_macos
|
|
||||||
OPTIONS = '''
|
OPTIONS = '''
|
||||||
--class
|
--class
|
||||||
dest=cls
|
dest=cls
|
||||||
@@ -32,9 +32,21 @@ only use this if you are running a program that does not set titles.
|
|||||||
|
|
||||||
--config
|
--config
|
||||||
type=list
|
type=list
|
||||||
default={config_path}
|
|
||||||
Specify a path to the configuration file(s) to use.
|
Specify a path to the configuration file(s) to use.
|
||||||
Can be specified multiple times to read multiple configuration files in sequence, which are merged.
|
Can be specified multiple times to read multiple configuration files in
|
||||||
|
sequence, which are merged. Use the special value NONE to not load a config
|
||||||
|
file.
|
||||||
|
|
||||||
|
If this option is not specified, config files are searched for in the order:
|
||||||
|
"$XDG_CONFIG_HOME/kitty/kitty.conf", "~/.config/kitty/kitty.conf", {macos_confpath}
|
||||||
|
"$XDG_CONFIG_DIRS/kitty/kitty.conf". The first one that exists is used as the
|
||||||
|
config file.
|
||||||
|
|
||||||
|
If the environment variable "KITTY_CONFIG_DIRECTORY" is specified, that
|
||||||
|
directory is always used and the above searching does not happen.
|
||||||
|
|
||||||
|
If "/etc/xdg/kitty/kitty.conf" exists it is used as a base config file onto
|
||||||
|
which any user config files are merged.
|
||||||
|
|
||||||
|
|
||||||
--override -o
|
--override -o
|
||||||
@@ -122,6 +134,11 @@ Debug OpenGL commands. This will cause all OpenGL calls to check for errors inst
|
|||||||
--debug-font-fallback
|
--debug-font-fallback
|
||||||
type=bool-set
|
type=bool-set
|
||||||
Print out information about the selection of fallback fonts for characters not present in the main font.
|
Print out information about the selection of fallback fonts for characters not present in the main font.
|
||||||
|
|
||||||
|
|
||||||
|
--debug-config
|
||||||
|
type=bool-set
|
||||||
|
Print out information about the system and kitty configuration.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
@@ -201,10 +218,10 @@ def parse_option_spec(spec=OPTIONS):
|
|||||||
current_cmd['choices'] = {x.strip() for x in current_cmd['choices'].split(',')}
|
current_cmd['choices'] = {x.strip() for x in current_cmd['choices'].split(',')}
|
||||||
elif state is HELP:
|
elif state is HELP:
|
||||||
if line:
|
if line:
|
||||||
current_cmd['help'] += ' ' + line
|
current_cmd['help'] += ' ' + line.lstrip()
|
||||||
else:
|
else:
|
||||||
if prev_line:
|
if prev_line:
|
||||||
current_cmd['help'] += '\n'
|
current_cmd['help'] += '\n\n\t'
|
||||||
else:
|
else:
|
||||||
state = NORMAL
|
state = NORMAL
|
||||||
(seq if current_cmd.get('condition', True) else disabled).append(current_cmd)
|
(seq if current_cmd.get('condition', True) else disabled).append(current_cmd)
|
||||||
@@ -453,7 +470,7 @@ def parse_cmdline(oc, disabled, args=None):
|
|||||||
def options_spec():
|
def options_spec():
|
||||||
if not hasattr(options_spec, 'ans'):
|
if not hasattr(options_spec, 'ans'):
|
||||||
options_spec.ans = OPTIONS.format(
|
options_spec.ans = OPTIONS.format(
|
||||||
appname=appname, config_path=defconf,
|
appname=appname, macos_confpath='~/Library/Preferences/kitty/kitty.conf' if is_macos else '',
|
||||||
window_layout_choices=', '.join(all_layouts)
|
window_layout_choices=', '.join(all_layouts)
|
||||||
)
|
)
|
||||||
return options_spec.ans
|
return options_spec.ans
|
||||||
@@ -466,8 +483,85 @@ def parse_args(args=None, ospec=options_spec, usage=None, message=None, appname=
|
|||||||
return parse_cmdline(oc, disabled, args=args)
|
return parse_cmdline(oc, disabled, args=args)
|
||||||
|
|
||||||
|
|
||||||
def create_opts(args):
|
SYSTEM_CONF = '/etc/xdg/kitty/kitty.conf'
|
||||||
config = args.config or (defconf, )
|
|
||||||
|
|
||||||
|
def resolve_config(config_files_on_cmd_line):
|
||||||
|
if config_files_on_cmd_line:
|
||||||
|
if 'NONE' not in config_files_on_cmd_line:
|
||||||
|
yield SYSTEM_CONF
|
||||||
|
for cf in config_files_on_cmd_line:
|
||||||
|
yield cf
|
||||||
|
else:
|
||||||
|
yield SYSTEM_CONF
|
||||||
|
yield defconf
|
||||||
|
|
||||||
|
|
||||||
|
def print_shortcut(key, action):
|
||||||
|
if not getattr(print_shortcut, 'maps', None):
|
||||||
|
from kitty.keys import defines
|
||||||
|
v = vars(defines)
|
||||||
|
mmap = {m.split('_')[-1].lower(): x for m, x in v.items() if m.startswith('GLFW_MOD_')}
|
||||||
|
kmap = {k.split('_')[-1].lower(): x for k, x in v.items() if k.startswith('GLFW_KEY_')}
|
||||||
|
krmap = {v: k for k, v in kmap.items()}
|
||||||
|
print_shortcut.maps = mmap, krmap
|
||||||
|
mmap, krmap = print_shortcut.maps
|
||||||
|
names = []
|
||||||
|
mods, key = key
|
||||||
|
for name, val in mmap.items():
|
||||||
|
if mods & val:
|
||||||
|
names.append(name)
|
||||||
|
if key:
|
||||||
|
names.append(krmap[key])
|
||||||
|
print('\t', '+'.join(names), action)
|
||||||
|
|
||||||
|
|
||||||
|
def compare_keymaps(final, initial):
|
||||||
|
added = set(final) - set(initial)
|
||||||
|
removed = set(initial) - set(final)
|
||||||
|
changed = {k for k in set(final) & set(initial) if final[k] != initial[k]}
|
||||||
|
if added:
|
||||||
|
print(title('Added shortcuts:'))
|
||||||
|
for k in added:
|
||||||
|
print_shortcut(k, final[k])
|
||||||
|
if removed:
|
||||||
|
print(title('Removed shortcuts:'))
|
||||||
|
for k in removed:
|
||||||
|
print_shortcut(k, initial[k])
|
||||||
|
if changed:
|
||||||
|
print(title('Changed shortcuts:'))
|
||||||
|
for k in changed:
|
||||||
|
print_shortcut(k, final[k])
|
||||||
|
|
||||||
|
|
||||||
|
def compare_opts(opts):
|
||||||
|
print('\nConfig options different from defaults:')
|
||||||
|
for f in sorted(defaults._fields):
|
||||||
|
if getattr(opts, f) != getattr(defaults, f):
|
||||||
|
if f == 'keymap':
|
||||||
|
compare_keymaps(opts.keymap, defaults.keymap)
|
||||||
|
else:
|
||||||
|
print(title('{:20s}'.format(f)), getattr(opts, f))
|
||||||
|
|
||||||
|
|
||||||
|
def create_opts(args, debug_config=False):
|
||||||
|
config = tuple(resolve_config(args.config))
|
||||||
|
if debug_config:
|
||||||
|
print(version())
|
||||||
|
print(' '.join(os.uname()))
|
||||||
|
if is_macos:
|
||||||
|
print(' '.join(subprocess.check_output(['sw_vers']).decode('utf-8').splitlines()).strip())
|
||||||
|
else:
|
||||||
|
print('Running under:', green('Wayland' if is_wayland else 'X11'))
|
||||||
|
if os.path.exists('/etc/issue'):
|
||||||
|
print(open('/etc/issue', encoding='utf-8', errors='replace').read().strip())
|
||||||
|
if os.path.exists('/etc/lsb-release'):
|
||||||
|
print(open('/etc/lsb-release', encoding='utf-8', errors='replace').read().strip())
|
||||||
|
config = tuple(x for x in config if os.path.exists(x))
|
||||||
|
if config:
|
||||||
|
print(green('Loaded config files:'), ', '.join(config))
|
||||||
overrides = (a.replace('=', ' ', 1) for a in args.override or ())
|
overrides = (a.replace('=', ' ', 1) for a in args.override or ())
|
||||||
opts = load_config(*config, overrides=overrides)
|
opts = load_config(*config, overrides=overrides)
|
||||||
|
if debug_config:
|
||||||
|
compare_opts(opts)
|
||||||
return opts
|
return opts
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ def to_cursor_shape(x):
|
|||||||
def parse_mods(parts):
|
def parse_mods(parts):
|
||||||
|
|
||||||
def map_mod(m):
|
def map_mod(m):
|
||||||
return {'CTRL': 'CONTROL', 'CMD': 'SUPER', 'OPTION': 'ALT'}.get(m, m)
|
return {'CTRL': 'CONTROL', 'CMD': 'SUPER', '⌘': 'SUPER', '⌥': 'ALT', 'OPTION': 'ALT'}.get(m, m)
|
||||||
|
|
||||||
mods = 0
|
mods = 0
|
||||||
for m in parts:
|
for m in parts:
|
||||||
@@ -293,7 +293,6 @@ type_map = {
|
|||||||
'macos_option_as_alt': to_bool,
|
'macos_option_as_alt': to_bool,
|
||||||
'macos_titlebar_color': macos_titlebar_color,
|
'macos_titlebar_color': macos_titlebar_color,
|
||||||
'box_drawing_scale': box_drawing_scale,
|
'box_drawing_scale': box_drawing_scale,
|
||||||
'x11_bell_volume': int,
|
|
||||||
'background_opacity': unit_float,
|
'background_opacity': unit_float,
|
||||||
'tab_separator': tab_separator,
|
'tab_separator': tab_separator,
|
||||||
'active_tab_font_style': tab_font_style,
|
'active_tab_font_style': tab_font_style,
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ from collections import namedtuple
|
|||||||
from .fast_data_types import set_boss as set_c_boss
|
from .fast_data_types import set_boss as set_c_boss
|
||||||
|
|
||||||
appname = 'kitty'
|
appname = 'kitty'
|
||||||
version = (0, 8, 2)
|
version = (0, 8, 3)
|
||||||
str_version = '.'.join(map(str, version))
|
str_version = '.'.join(map(str, version))
|
||||||
_plat = sys.platform.lower()
|
_plat = sys.platform.lower()
|
||||||
is_macos = 'darwin' in _plat
|
is_macos = 'darwin' in _plat
|
||||||
@@ -27,7 +27,22 @@ def _get_config_dir():
|
|||||||
if 'KITTY_CONFIG_DIRECTORY' in os.environ:
|
if 'KITTY_CONFIG_DIRECTORY' in os.environ:
|
||||||
return os.path.abspath(os.path.expanduser(os.environ['KITTY_CONFIG_DIRECTORY']))
|
return os.path.abspath(os.path.expanduser(os.environ['KITTY_CONFIG_DIRECTORY']))
|
||||||
|
|
||||||
candidate = os.path.abspath(os.path.expanduser(os.environ.get('XDG_CONFIG_HOME') or ('~/Library/Preferences' if is_macos else '~/.config')))
|
locations = []
|
||||||
|
if 'XDG_CONFIG_HOME' in os.environ:
|
||||||
|
locations.append(os.path.abspath(os.path.expanduser(os.environ['XDG_CONFIG_HOME'])))
|
||||||
|
locations.append(os.path.expanduser('~/.config'))
|
||||||
|
if is_macos:
|
||||||
|
locations.append(os.path.expanduser('~/Library/Preferences'))
|
||||||
|
if 'XDG_CONFIG_DIRS' in os.environ:
|
||||||
|
for loc in os.environ['XDG_CONFIG_DIRS'].split(os.pathsep):
|
||||||
|
locations.append(os.path.abspath(os.path.expanduser(os.environ['XDG_CONFIG_HOME'])))
|
||||||
|
for loc in locations:
|
||||||
|
if loc:
|
||||||
|
q = os.path.join(loc, appname)
|
||||||
|
if os.access(q, os.W_OK) and os.path.exists(os.path.join(q, 'kitty.conf')):
|
||||||
|
return q
|
||||||
|
|
||||||
|
candidate = os.path.abspath(os.path.expanduser(os.environ.get('XDG_CONFIG_HOME') or '~/.config'))
|
||||||
ans = os.path.join(candidate, appname)
|
ans = os.path.join(candidate, appname)
|
||||||
os.makedirs(ans, exist_ok=True)
|
os.makedirs(ans, exist_ok=True)
|
||||||
return ans
|
return ans
|
||||||
@@ -46,10 +61,7 @@ def _get_cache_dir():
|
|||||||
else:
|
else:
|
||||||
candidate = os.environ.get('XDG_CACHE_HOME', '~/.cache')
|
candidate = os.environ.get('XDG_CACHE_HOME', '~/.cache')
|
||||||
candidate = os.path.join(os.path.expanduser(candidate), appname)
|
candidate = os.path.join(os.path.expanduser(candidate), appname)
|
||||||
try:
|
os.makedirs(candidate, exist_ok=True)
|
||||||
os.makedirs(candidate)
|
|
||||||
except FileExistsError:
|
|
||||||
pass
|
|
||||||
return candidate
|
return candidate
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -278,8 +278,12 @@ calc_cell_width(Face *self) {
|
|||||||
unsigned int ans = 0;
|
unsigned int ans = 0;
|
||||||
for (char_type i = 32; i < 128; i++) {
|
for (char_type i = 32; i < 128; i++) {
|
||||||
int glyph_index = FT_Get_Char_Index(self->face, i);
|
int glyph_index = FT_Get_Char_Index(self->face, i);
|
||||||
if (load_glyph(self, glyph_index, FT_LOAD_DEFAULT)) {
|
// We actually render the bitmap and get its width even though this is very slow, because
|
||||||
ans = MAX(ans, (unsigned long)ceilf((float)self->face->glyph->metrics.horiAdvance / 64.f));
|
// there are fonts for which the horizontal advance is incorrect, see https://github.com/kovidgoyal/kitty/issues/352
|
||||||
|
if (load_glyph(self, glyph_index, FT_LOAD_RENDER)) {
|
||||||
|
unsigned int horizontal_advance = (unsigned int)ceilf((float)self->face->glyph->metrics.horiAdvance / 64.f);
|
||||||
|
ans = MAX(ans, self->face->glyph->bitmap.width);
|
||||||
|
ans = MAX(ans, horizontal_advance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ans;
|
return ans;
|
||||||
|
|||||||
2
kitty/glfw-wrapper.h
generated
2
kitty/glfw-wrapper.h
generated
@@ -1585,7 +1585,7 @@ typedef void (*glfwRequestWindowAttention_func)(GLFWwindow*);
|
|||||||
glfwRequestWindowAttention_func glfwRequestWindowAttention_impl;
|
glfwRequestWindowAttention_func glfwRequestWindowAttention_impl;
|
||||||
#define glfwRequestWindowAttention glfwRequestWindowAttention_impl
|
#define glfwRequestWindowAttention glfwRequestWindowAttention_impl
|
||||||
|
|
||||||
typedef int (*glfwWindowBell_func)(GLFWwindow*, int64_t);
|
typedef int (*glfwWindowBell_func)(GLFWwindow*);
|
||||||
glfwWindowBell_func glfwWindowBell_impl;
|
glfwWindowBell_func glfwWindowBell_impl;
|
||||||
#define glfwWindowBell glfwWindowBell_impl
|
#define glfwWindowBell glfwWindowBell_impl
|
||||||
|
|
||||||
|
|||||||
@@ -604,7 +604,7 @@ ring_audio_bell(OSWindow *w) {
|
|||||||
if (now - last_bell_at <= 0.1) return;
|
if (now - last_bell_at <= 0.1) return;
|
||||||
last_bell_at = now;
|
last_bell_at = now;
|
||||||
if (w->handle) {
|
if (w->handle) {
|
||||||
glfwWindowBell(w->handle, OPT(x11_bell_volume));
|
glfwWindowBell(w->handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -392,6 +392,7 @@ map ctrl+shift+q close_tab
|
|||||||
map ctrl+shift+l next_layout
|
map ctrl+shift+l next_layout
|
||||||
map ctrl+shift+. move_tab_forward
|
map ctrl+shift+. move_tab_forward
|
||||||
map ctrl+shift+, move_tab_backward
|
map ctrl+shift+, move_tab_backward
|
||||||
|
map ctrl+shift+alt+t set_tab_title
|
||||||
# You can also create shortcuts to go to specific tabs, with 1 being the first tab
|
# You can also create shortcuts to go to specific tabs, with 1 being the first tab
|
||||||
# map ctrl+alt+1 goto_tab 1
|
# map ctrl+alt+1 goto_tab 1
|
||||||
# map ctrl+alt+2 goto_tab 2
|
# map ctrl+alt+2 goto_tab 2
|
||||||
@@ -462,8 +463,4 @@ macos_hide_titlebar no
|
|||||||
# break any Alt+key keyboard shortcuts in your terminal programs, but you
|
# break any Alt+key keyboard shortcuts in your terminal programs, but you
|
||||||
# can use the macOS unicode input technique.
|
# can use the macOS unicode input technique.
|
||||||
macos_option_as_alt yes
|
macos_option_as_alt yes
|
||||||
|
|
||||||
# The number is a percentage of maximum volume.
|
|
||||||
# See man XBell for details.
|
|
||||||
x11_bell_volume 80
|
|
||||||
# }}}
|
# }}}
|
||||||
|
|||||||
@@ -141,10 +141,17 @@ def _main():
|
|||||||
if is_macos and os.environ.pop('KITTY_LAUNCHED_BY_LAUNCH_SERVICES', None) == '1':
|
if is_macos and os.environ.pop('KITTY_LAUNCHED_BY_LAUNCH_SERVICES', None) == '1':
|
||||||
os.chdir(os.path.expanduser('~'))
|
os.chdir(os.path.expanduser('~'))
|
||||||
args = macos_cmdline()
|
args = macos_cmdline()
|
||||||
if not os.path.isdir(os.getcwd()):
|
try:
|
||||||
|
cwd_ok = os.path.isdir(os.getcwd())
|
||||||
|
except Exception:
|
||||||
|
cwd_ok = False
|
||||||
|
if not cwd_ok:
|
||||||
os.chdir(os.path.expanduser('~'))
|
os.chdir(os.path.expanduser('~'))
|
||||||
args, rest = parse_args(args=args)
|
args, rest = parse_args(args=args)
|
||||||
args.args = rest
|
args.args = rest
|
||||||
|
if args.debug_config:
|
||||||
|
create_opts(args, debug_config=True)
|
||||||
|
return
|
||||||
if getattr(args, 'detach', False):
|
if getattr(args, 'detach', False):
|
||||||
detach()
|
detach()
|
||||||
if args.cmd:
|
if args.cmd:
|
||||||
|
|||||||
@@ -16,13 +16,13 @@
|
|||||||
static MouseShape mouse_cursor_shape = BEAM;
|
static MouseShape mouse_cursor_shape = BEAM;
|
||||||
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
|
typedef enum MouseActions { PRESS, RELEASE, DRAG, MOVE } MouseAction;
|
||||||
|
|
||||||
|
// Encoding of mouse events {{{
|
||||||
#define SHIFT_INDICATOR (1 << 2)
|
#define SHIFT_INDICATOR (1 << 2)
|
||||||
#define ALT_INDICATOR (1 << 3)
|
#define ALT_INDICATOR (1 << 3)
|
||||||
#define CONTROL_INDICATOR (1 << 4)
|
#define CONTROL_INDICATOR (1 << 4)
|
||||||
#define MOTION_INDICATOR (1 << 5)
|
#define MOTION_INDICATOR (1 << 5)
|
||||||
#define EXTRA_BUTTON_INDICATOR (1 << 6)
|
#define EXTRA_BUTTON_INDICATOR (1 << 6)
|
||||||
|
|
||||||
static int last_multi_clicks = 0;
|
|
||||||
|
|
||||||
static inline unsigned int
|
static inline unsigned int
|
||||||
button_map(int button) {
|
button_map(int button) {
|
||||||
@@ -91,6 +91,8 @@ encode_mouse_event(Window *w, int button, MouseAction action, int mods) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// }}}
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
contains_mouse(Window *w) {
|
contains_mouse(Window *w) {
|
||||||
WindowGeometry *g = &w->geometry;
|
WindowGeometry *g = &w->geometry;
|
||||||
@@ -118,10 +120,9 @@ update_drag(bool from_button, Window *w, bool is_release, int modifiers) {
|
|||||||
Screen *screen = w->render_data.screen;
|
Screen *screen = w->render_data.screen;
|
||||||
if (from_button) {
|
if (from_button) {
|
||||||
if (is_release) screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true);
|
if (is_release) screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, true);
|
||||||
else screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y, modifiers == (int)OPT(rectangle_select_modifiers));
|
else screen_start_selection(screen, w->mouse_cell_x, w->mouse_cell_y, modifiers == (int)OPT(rectangle_select_modifiers), EXTEND_CELL);
|
||||||
} else if (screen->selection.in_progress) {
|
} else if (screen->selection.in_progress) {
|
||||||
screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
||||||
call_boss(set_primary_selection, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,12 +153,8 @@ drag_scroll(Window *w, OSWindow *frame) {
|
|||||||
static inline void
|
static inline void
|
||||||
extend_selection(Window *w) {
|
extend_selection(Window *w) {
|
||||||
Screen *screen = w->render_data.screen;
|
Screen *screen = w->render_data.screen;
|
||||||
index_type start, end;
|
|
||||||
if (screen_has_selection(screen)) {
|
if (screen_has_selection(screen)) {
|
||||||
bool found_selectable_word = screen_selection_range_for_word(screen, w->mouse_cell_x, w->mouse_cell_y, &start, &end);
|
screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
||||||
if (last_multi_clicks >= 2 && found_selectable_word) screen_update_selection(screen, end, w->mouse_cell_y, true);
|
|
||||||
else screen_update_selection(screen, w->mouse_cell_x, w->mouse_cell_y, false);
|
|
||||||
call_boss(set_primary_selection, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -234,20 +231,22 @@ multi_click(Window *w, unsigned int count) {
|
|||||||
Screen *screen = w->render_data.screen;
|
Screen *screen = w->render_data.screen;
|
||||||
index_type start, end;
|
index_type start, end;
|
||||||
bool found_selection = false;
|
bool found_selection = false;
|
||||||
|
SelectionExtendMode mode = EXTEND_CELL;
|
||||||
switch(count) {
|
switch(count) {
|
||||||
case 2:
|
case 2:
|
||||||
found_selection = screen_selection_range_for_word(screen, w->mouse_cell_x, w->mouse_cell_y, &start, &end);
|
found_selection = screen_selection_range_for_word(screen, w->mouse_cell_x, w->mouse_cell_y, &start, &end);
|
||||||
|
mode = EXTEND_WORD;
|
||||||
break;
|
break;
|
||||||
case 3:
|
case 3:
|
||||||
found_selection = screen_selection_range_for_line(screen, w->mouse_cell_y, &start, &end);
|
found_selection = screen_selection_range_for_line(screen, w->mouse_cell_y, &start, &end);
|
||||||
|
mode = EXTEND_LINE;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (found_selection) {
|
if (found_selection) {
|
||||||
screen_start_selection(screen, start, w->mouse_cell_y, false);
|
screen_start_selection(screen, start, w->mouse_cell_y, false, mode);
|
||||||
screen_update_selection(screen, end, w->mouse_cell_y, true);
|
screen_update_selection(screen, end, w->mouse_cell_y, false);
|
||||||
call_boss(set_primary_selection, NULL);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -260,11 +259,9 @@ HANDLER(add_click) {
|
|||||||
q->length++;
|
q->length++;
|
||||||
// Now dispatch the multi-click if any
|
// Now dispatch the multi-click if any
|
||||||
if (q->length > 2 && N(1).at - N(3).at <= 2 * OPT(click_interval)) {
|
if (q->length > 2 && N(1).at - N(3).at <= 2 * OPT(click_interval)) {
|
||||||
last_multi_clicks = 3;
|
|
||||||
multi_click(w, 3);
|
multi_click(w, 3);
|
||||||
q->length = 0;
|
q->length = 0;
|
||||||
} else if (q->length > 1 && N(1).at - N(2).at <= OPT(click_interval)) {
|
} else if (q->length > 1 && N(1).at - N(2).at <= OPT(click_interval)) {
|
||||||
last_multi_clicks = 2;
|
|
||||||
multi_click(w, 2);
|
multi_click(w, 2);
|
||||||
}
|
}
|
||||||
#undef N
|
#undef N
|
||||||
@@ -294,14 +291,9 @@ HANDLER(handle_button_event) {
|
|||||||
switch(button) {
|
switch(button) {
|
||||||
case GLFW_MOUSE_BUTTON_LEFT:
|
case GLFW_MOUSE_BUTTON_LEFT:
|
||||||
update_drag(true, w, is_release, modifiers);
|
update_drag(true, w, is_release, modifiers);
|
||||||
last_multi_clicks = 0;
|
|
||||||
if (is_release) {
|
if (is_release) {
|
||||||
if (modifiers == (int)OPT(open_url_modifiers)) {
|
if (modifiers == (int)OPT(open_url_modifiers)) open_url(w);
|
||||||
open_url(w);
|
} else add_click(w, button, modifiers, window_idx);
|
||||||
} else {
|
|
||||||
if (is_release) add_click(w, button, modifiers, window_idx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case GLFW_MOUSE_BUTTON_MIDDLE:
|
case GLFW_MOUSE_BUTTON_MIDDLE:
|
||||||
if (is_release && !modifiers) { call_boss(paste_from_selection, NULL); return; }
|
if (is_release && !modifiers) { call_boss(paste_from_selection, NULL); return; }
|
||||||
|
|||||||
@@ -310,7 +310,7 @@ dispatch_osc(Screen *screen, PyObject DUMP_UNUSED *dump_callback) {
|
|||||||
}
|
}
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
code = utoi(screen->parser_buf, i);
|
code = utoi(screen->parser_buf, i);
|
||||||
if (i < limit - 1 && screen->parser_buf[i] == ';') i++;
|
if (i < limit && screen->parser_buf[i] == ';') i++;
|
||||||
}
|
}
|
||||||
PyObject *string = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, screen->parser_buf + i, limit - i);
|
PyObject *string = PyUnicode_FromKindAndData(PyUnicode_4BYTE_KIND, screen->parser_buf + i, limit - i);
|
||||||
if (string != NULL) {
|
if (string != NULL) {
|
||||||
|
|||||||
@@ -1066,7 +1066,7 @@ bool
|
|||||||
screen_invert_colors(Screen *self) {
|
screen_invert_colors(Screen *self) {
|
||||||
bool inverted = false;
|
bool inverted = false;
|
||||||
if (self->start_visual_bell_at > 0) {
|
if (self->start_visual_bell_at > 0) {
|
||||||
if (monotonic() - self->start_visual_bell_at <= global_state.opts.visual_bell_duration) inverted = true;
|
if (monotonic() - self->start_visual_bell_at <= OPT(visual_bell_duration)) inverted = true;
|
||||||
else self->start_visual_bell_at = 0;
|
else self->start_visual_bell_at = 0;
|
||||||
}
|
}
|
||||||
if (self->modes.mDECSCNM) inverted = inverted ? false : true;
|
if (self->modes.mDECSCNM) inverted = inverted ? false : true;
|
||||||
@@ -1076,6 +1076,7 @@ screen_invert_colors(Screen *self) {
|
|||||||
void
|
void
|
||||||
screen_bell(Screen *self) {
|
screen_bell(Screen *self) {
|
||||||
request_window_attention(self->window_id, OPT(enable_audio_bell));
|
request_window_attention(self->window_id, OPT(enable_audio_bell));
|
||||||
|
if (OPT(visual_bell_duration) > 0.0f) self->start_visual_bell_at = monotonic();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -1410,7 +1411,7 @@ screen_apply_selection(Screen *self, void *address, size_t size) {
|
|||||||
self->last_selection_scrolled_by = self->scrolled_by;
|
self->last_selection_scrolled_by = self->scrolled_by;
|
||||||
self->selection_updated_once = true;
|
self->selection_updated_once = true;
|
||||||
selection_limits_(selection, &self->last_rendered_selection_start, &self->last_rendered_selection_end);
|
selection_limits_(selection, &self->last_rendered_selection_start, &self->last_rendered_selection_end);
|
||||||
apply_selection(self, address, &self->last_rendered_selection_start, &self->last_rendered_selection_end, 1, self->rectangle_select);
|
apply_selection(self, address, &self->last_rendered_selection_start, &self->last_rendered_selection_end, 1, self->selection.rectangle_select);
|
||||||
selection_limits_(url_range, &self->last_rendered_url_start, &self->last_rendered_url_end);
|
selection_limits_(url_range, &self->last_rendered_url_start, &self->last_rendered_url_end);
|
||||||
apply_selection(self, address, &self->last_rendered_url_start, &self->last_rendered_url_end, 2, false);
|
apply_selection(self, address, &self->last_rendered_url_start, &self->last_rendered_url_end, 2, false);
|
||||||
}
|
}
|
||||||
@@ -1626,9 +1627,17 @@ WRAP0(carriage_return)
|
|||||||
WRAP2(resize, 1, 1)
|
WRAP2(resize, 1, 1)
|
||||||
WRAP2(set_margins, 1, 1)
|
WRAP2(set_margins, 1, 1)
|
||||||
WRAP2(rescale_images, 1, 1)
|
WRAP2(rescale_images, 1, 1)
|
||||||
WRAP2B(start_selection)
|
|
||||||
WRAP2B(update_selection)
|
WRAP2B(update_selection)
|
||||||
|
|
||||||
|
static PyObject*
|
||||||
|
start_selection(Screen *self, PyObject *args) {
|
||||||
|
unsigned int x, y;
|
||||||
|
int rectangle_select = 0, extend_mode = EXTEND_CELL;
|
||||||
|
if (!PyArg_ParseTuple(args, "II|pp", &x, &y, &rectangle_select, &extend_mode)) return NULL;
|
||||||
|
screen_start_selection(self, x, y, rectangle_select, extend_mode);
|
||||||
|
Py_RETURN_NONE;
|
||||||
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
change_scrollback_size(Screen *self, PyObject *args) {
|
change_scrollback_size(Screen *self, PyObject *args) {
|
||||||
unsigned int count = 1;
|
unsigned int count = 1;
|
||||||
@@ -1643,7 +1652,7 @@ text_for_selection(Screen *self, PyObject *a UNUSED) {
|
|||||||
full_selection_limits_(selection, &start, &end);
|
full_selection_limits_(selection, &start, &end);
|
||||||
PyObject *ans = NULL;
|
PyObject *ans = NULL;
|
||||||
if (start.y == end.y && start.x == end.x) ans = PyTuple_New(0);
|
if (start.y == end.y && start.x == end.x) ans = PyTuple_New(0);
|
||||||
else text_for_range(ans, start, end, self->rectangle_select, true, range_line_, int);
|
else text_for_range(ans, start, end, self->selection.rectangle_select, true, range_line_, int);
|
||||||
return ans;
|
return ans;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1733,10 +1742,10 @@ screen_is_selection_dirty(Screen *self) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
screen_start_selection(Screen *self, index_type x, index_type y, bool rectangle_select) {
|
screen_start_selection(Screen *self, index_type x, index_type y, bool rectangle_select, SelectionExtendMode extend_mode) {
|
||||||
self->rectangle_select = rectangle_select;
|
|
||||||
#define A(attr, val) self->selection.attr = val;
|
#define A(attr, val) self->selection.attr = val;
|
||||||
A(start_x, x); A(end_x, x); A(start_y, y); A(end_y, y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by); A(in_progress, true);
|
A(start_x, x); A(end_x, x); A(start_y, y); A(end_y, y); A(start_scrolled_by, self->scrolled_by); A(end_scrolled_by, self->scrolled_by);
|
||||||
|
A(in_progress, true); A(rectangle_select, rectangle_select); A(extend_mode, extend_mode);
|
||||||
#undef A
|
#undef A
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1751,6 +1760,20 @@ void
|
|||||||
screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
screen_update_selection(Screen *self, index_type x, index_type y, bool ended) {
|
||||||
self->selection.end_x = x; self->selection.end_y = y; self->selection.end_scrolled_by = self->scrolled_by;
|
self->selection.end_x = x; self->selection.end_y = y; self->selection.end_scrolled_by = self->scrolled_by;
|
||||||
if (ended) self->selection.in_progress = false;
|
if (ended) self->selection.in_progress = false;
|
||||||
|
index_type start, end;
|
||||||
|
bool found = false;
|
||||||
|
switch(self->selection.extend_mode) {
|
||||||
|
case EXTEND_WORD:
|
||||||
|
found = screen_selection_range_for_word(self, x, y, &start, &end);
|
||||||
|
break;
|
||||||
|
case EXTEND_LINE:
|
||||||
|
found = screen_selection_range_for_line(self, y, &start, &end);
|
||||||
|
break;
|
||||||
|
case EXTEND_CELL:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (found) self->selection.end_x = end;
|
||||||
|
call_boss(set_primary_selection, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static PyObject*
|
static PyObject*
|
||||||
|
|||||||
@@ -22,9 +22,12 @@ typedef struct {
|
|||||||
unsigned int x, y;
|
unsigned int x, y;
|
||||||
} SelectionBoundary;
|
} SelectionBoundary;
|
||||||
|
|
||||||
|
typedef enum SelectionExtendModes { EXTEND_CELL, EXTEND_WORD, EXTEND_LINE } SelectionExtendMode;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
unsigned int start_x, start_y, start_scrolled_by, end_x, end_y, end_scrolled_by;
|
unsigned int start_x, start_y, start_scrolled_by, end_x, end_y, end_scrolled_by;
|
||||||
bool in_progress;
|
bool in_progress, rectangle_select;
|
||||||
|
SelectionExtendMode extend_mode;
|
||||||
} Selection;
|
} Selection;
|
||||||
|
|
||||||
#define SAVEPOINTS_SZ 256
|
#define SAVEPOINTS_SZ 256
|
||||||
@@ -61,7 +64,7 @@ typedef struct {
|
|||||||
Selection selection;
|
Selection selection;
|
||||||
SelectionBoundary last_rendered_selection_start, last_rendered_selection_end, last_rendered_url_start, last_rendered_url_end;
|
SelectionBoundary last_rendered_selection_start, last_rendered_selection_end, last_rendered_url_start, last_rendered_url_end;
|
||||||
Selection url_range;
|
Selection url_range;
|
||||||
bool use_latin1, selection_updated_once, is_dirty, scroll_changed, rectangle_select;
|
bool use_latin1, selection_updated_once, is_dirty, scroll_changed;
|
||||||
Cursor *cursor;
|
Cursor *cursor;
|
||||||
SavepointBuffer main_savepoints, alt_savepoints;
|
SavepointBuffer main_savepoints, alt_savepoints;
|
||||||
SavemodesBuffer modes_savepoints;
|
SavemodesBuffer modes_savepoints;
|
||||||
@@ -156,7 +159,7 @@ void screen_update_cell_data(Screen *self, void *address, size_t sz);
|
|||||||
bool screen_is_cursor_visible(Screen *self);
|
bool screen_is_cursor_visible(Screen *self);
|
||||||
bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end);
|
bool screen_selection_range_for_line(Screen *self, index_type y, index_type *start, index_type *end);
|
||||||
bool screen_selection_range_for_word(Screen *self, index_type x, index_type y, index_type *start, index_type *end);
|
bool screen_selection_range_for_word(Screen *self, index_type x, index_type y, index_type *start, index_type *end);
|
||||||
void screen_start_selection(Screen *self, index_type x, index_type y, bool);
|
void screen_start_selection(Screen *self, index_type x, index_type y, bool, SelectionExtendMode);
|
||||||
void screen_update_selection(Screen *self, index_type x, index_type y, bool ended);
|
void screen_update_selection(Screen *self, index_type x, index_type y, bool ended);
|
||||||
bool screen_history_scroll(Screen *self, int amt, bool upwards);
|
bool screen_history_scroll(Screen *self, int amt, bool upwards);
|
||||||
Line* screen_visual_line(Screen *self, index_type y);
|
Line* screen_visual_line(Screen *self, index_type y);
|
||||||
|
|||||||
@@ -214,9 +214,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G
|
|||||||
struct CellRenderData {
|
struct CellRenderData {
|
||||||
GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity;
|
GLfloat xstart, ystart, dx, dy, sprite_dx, sprite_dy, background_opacity;
|
||||||
|
|
||||||
GLuint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, url_color, url_style;
|
GLuint default_fg, default_bg, highlight_fg, highlight_bg, cursor_color, url_color, url_style, inverted;
|
||||||
|
|
||||||
GLint color1, color2;
|
|
||||||
|
|
||||||
GLuint xnum, ynum, cursor_x, cursor_y, cursor_w;
|
GLuint xnum, ynum, cursor_x, cursor_y, cursor_w;
|
||||||
};
|
};
|
||||||
@@ -241,7 +239,7 @@ cell_update_uniform_block(ssize_t vao_idx, Screen *screen, int uniform_buffer, G
|
|||||||
unsigned int x, y, z;
|
unsigned int x, y, z;
|
||||||
sprite_tracker_current_layout(&x, &y, &z);
|
sprite_tracker_current_layout(&x, &y, &z);
|
||||||
rd->sprite_dx = 1.0f / (float)x; rd->sprite_dy = 1.0f / (float)y;
|
rd->sprite_dx = 1.0f / (float)x; rd->sprite_dy = 1.0f / (float)y;
|
||||||
rd->color1 = inverted & 1; rd->color2 = 1 - (inverted & 1);
|
rd->inverted = inverted ? 1 : 0;
|
||||||
rd->background_opacity = OPT(background_opacity);
|
rd->background_opacity = OPT(background_opacity);
|
||||||
|
|
||||||
#define COLOR(name) colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.name, screen->color_profile->configured.name)
|
#define COLOR(name) colorprofile_to_color(screen->color_profile, screen->color_profile->overridden.name, screen->color_profile->configured.name)
|
||||||
|
|||||||
@@ -340,7 +340,6 @@ PYWRAP1(set_options) {
|
|||||||
S(inactive_text_alpha, PyFloat_AsDouble);
|
S(inactive_text_alpha, PyFloat_AsDouble);
|
||||||
S(cursor_shape, PyLong_AsLong);
|
S(cursor_shape, PyLong_AsLong);
|
||||||
S(url_style, PyLong_AsUnsignedLong);
|
S(url_style, PyLong_AsUnsignedLong);
|
||||||
S(x11_bell_volume, PyLong_AsLong);
|
|
||||||
S(tab_bar_edge, PyLong_AsLong);
|
S(tab_bar_edge, PyLong_AsLong);
|
||||||
S(mouse_hide_wait, PyFloat_AsDouble);
|
S(mouse_hide_wait, PyFloat_AsDouble);
|
||||||
S(wheel_scroll_multiplier, PyFloat_AsDouble);
|
S(wheel_scroll_multiplier, PyFloat_AsDouble);
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ typedef struct {
|
|||||||
bool macos_option_as_alt, macos_hide_titlebar;
|
bool macos_option_as_alt, macos_hide_titlebar;
|
||||||
int adjust_line_height_px, adjust_column_width_px;
|
int adjust_line_height_px, adjust_column_width_px;
|
||||||
float adjust_line_height_frac, adjust_column_width_frac;
|
float adjust_line_height_frac, adjust_column_width_frac;
|
||||||
int x11_bell_volume;
|
|
||||||
float background_opacity;
|
float background_opacity;
|
||||||
float inactive_text_alpha;
|
float inactive_text_alpha;
|
||||||
Edge tab_bar_edge;
|
Edge tab_bar_edge;
|
||||||
@@ -137,7 +136,7 @@ typedef struct {
|
|||||||
|
|
||||||
extern GlobalState global_state;
|
extern GlobalState global_state;
|
||||||
|
|
||||||
#define call_boss(name, ...) { \
|
#define call_boss(name, ...) if (global_state.boss) { \
|
||||||
PyObject *cret_ = PyObject_CallMethod(global_state.boss, #name, __VA_ARGS__); \
|
PyObject *cret_ = PyObject_CallMethod(global_state.boss, #name, __VA_ARGS__); \
|
||||||
if (cret_ == NULL) { PyErr_Print(); } \
|
if (cret_ == NULL) { PyErr_Print(); } \
|
||||||
else Py_DECREF(cret_); \
|
else Py_DECREF(cret_); \
|
||||||
|
|||||||
@@ -182,6 +182,9 @@ class TestParser(BaseTest):
|
|||||||
c.clear()
|
c.clear()
|
||||||
pb('\033]2;;;;\x07', ('set_title', ';;;'))
|
pb('\033]2;;;;\x07', ('set_title', ';;;'))
|
||||||
self.ae(c.titlebuf, ';;;')
|
self.ae(c.titlebuf, ';;;')
|
||||||
|
c.clear()
|
||||||
|
pb('\033]2;\x07', ('set_title', ''))
|
||||||
|
self.ae(c.titlebuf, '')
|
||||||
pb('\033]110\x07', ('set_dynamic_color', 110, ''))
|
pb('\033]110\x07', ('set_dynamic_color', 110, ''))
|
||||||
self.ae(c.colorbuf, '')
|
self.ae(c.colorbuf, '')
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user