Add support for Windows ConPTY API
This commit is contained in:
parent
ec6f756946
commit
f1bc6802e1
|
@ -10,6 +10,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
|
|
||||||
- New configuration field `visual_bell.color` allows changing the visual bell color
|
- New configuration field `visual_bell.color` allows changing the visual bell color
|
||||||
- Crashes on Windows are now also reported with a popup in addition to stderr
|
- Crashes on Windows are now also reported with a popup in addition to stderr
|
||||||
|
- Windows: New configuration field `enable_experimental_conpty_backend` which enables support
|
||||||
|
for the Pseudoconsole API (ConPTY) added in Windows 10 October 2018 (1809) update
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
@ -22,6 +24,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
- Fix panic after quitting Alacritty on macOS
|
- Fix panic after quitting Alacritty on macOS
|
||||||
- Tabs are no longer replaced by spaces when copying them to the clipboard
|
- Tabs are no longer replaced by spaces when copying them to the clipboard
|
||||||
- Alt modifier is no longer sent separately from the modified key
|
- Alt modifier is no longer sent separately from the modified key
|
||||||
|
- Various Windows issues, like color support and performance, through the new ConPTY
|
||||||
|
|
||||||
## Version 0.2.4
|
## Version 0.2.4
|
||||||
|
|
||||||
|
|
|
@ -51,14 +51,16 @@ dependencies = [
|
||||||
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
"libc 0.2.45 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"mio-anonymous-pipes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"notify 4.0.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"reqwest 0.9.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_derive 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -68,6 +70,7 @@ dependencies = [
|
||||||
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"vte 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winpty 0.1.0",
|
"winpty 0.1.0",
|
||||||
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -1268,6 +1271,17 @@ dependencies = [
|
||||||
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "mio-anonymous-pipes"
|
||||||
|
version = "0.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
dependencies = [
|
||||||
|
"mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"miow 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"spsc-buffer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "mio-extras"
|
name = "mio-extras"
|
||||||
version = "2.0.5"
|
version = "2.0.5"
|
||||||
|
@ -1913,7 +1927,7 @@ dependencies = [
|
||||||
"mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime 0.3.12 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"mime_guess 2.0.0-alpha.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"native-tls 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
"tokio 0.1.13 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2029,12 +2043,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.82"
|
version = "1.0.83"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2049,7 +2063,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"ryu 0.2.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -2059,7 +2073,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"itoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"url 1.7.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2070,7 +2084,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"dtoa 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"linked-hash-map 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)",
|
"serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
"yaml-rust 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
@ -2129,7 +2143,7 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "smithay-client-toolkit"
|
name = "smithay-client-toolkit"
|
||||||
version = "0.4.3"
|
version = "0.4.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"andrew 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"andrew 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2155,6 +2169,11 @@ dependencies = [
|
||||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "spsc-buffer"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "stable_deref_trait"
|
name = "stable_deref_trait"
|
||||||
version = "1.1.1"
|
version = "1.1.1"
|
||||||
|
@ -2645,6 +2664,11 @@ name = "widestring"
|
||||||
version = "0.2.2"
|
version = "0.2.2"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "widestring"
|
||||||
|
version = "0.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
@ -2707,7 +2731,7 @@ dependencies = [
|
||||||
"objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
"objc 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
"parking_lot 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
"percent-encoding 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"smithay-client-toolkit 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"smithay-client-toolkit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"wayland-client 0.21.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
"wayland-client 0.21.7 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
"winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
"x11-dl 2.18.3 (registry+https://github.com/rust-lang/crates.io-index)",
|
||||||
|
@ -2947,6 +2971,7 @@ dependencies = [
|
||||||
"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
|
"checksum miniz_oxide 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5ad30a47319c16cde58d0314f5d98202a80c9083b5f61178457403dfb14e509c"
|
||||||
"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
|
"checksum miniz_oxide_c_api 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "28edaef377517fd9fe3e085c37d892ce7acd1fbeab9239c5a36eec352d8a8b7e"
|
||||||
"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
|
"checksum mio 0.6.16 (registry+https://github.com/rust-lang/crates.io-index)" = "71646331f2619b1026cc302f87a2b8b648d5c6dd6937846a16cc8ce0f347f432"
|
||||||
|
"checksum mio-anonymous-pipes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f8c274c3c52dcd1d78c5d7ed841eca1e9ea2db8353f3b8ec25789cc62c471aaf"
|
||||||
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
|
"checksum mio-extras 2.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "46e73a04c2fa6250b8d802134d56d554a9ec2922bf977777c805ea5def61ce40"
|
||||||
"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
"checksum mio-named-pipes 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)" = "f5e374eff525ce1c5b7687c4cef63943e7686524a387933ad27ca7ec43779cb3"
|
||||||
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
|
"checksum mio-uds 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "966257a94e196b11bb43aca423754d87429960a768de9414f3691d6957abf125"
|
||||||
|
@ -3031,8 +3056,8 @@ dependencies = [
|
||||||
"checksum security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40d95f3d7da09612affe897f320d78264f0d2320f3e8eea27d12bd1bd94445e2"
|
"checksum security-framework-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "40d95f3d7da09612affe897f320d78264f0d2320f3e8eea27d12bd1bd94445e2"
|
||||||
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
"checksum semver 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403"
|
||||||
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
|
||||||
"checksum serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "6fa52f19aee12441d5ad11c9a00459122bd8f98707cadf9778c540674f1935b6"
|
"checksum serde 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)" = "157e12af46859e968da75dea9845530e13d03bcab2009a41b9b7bb3cf4eb3ec2"
|
||||||
"checksum serde_derive 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)" = "96a7f9496ac65a2db5929afa087b54f8fc5008dcfbe48a8874ed20049b0d6154"
|
"checksum serde_derive 1.0.83 (registry+https://github.com/rust-lang/crates.io-index)" = "9469829702497daf2daf3c190e130c3fa72f719920f73c86160d43e8f8d76951"
|
||||||
"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
|
"checksum serde_json 1.0.33 (registry+https://github.com/rust-lang/crates.io-index)" = "c37ccd6be3ed1fdf419ee848f7c758eb31b054d7cd3ae3600e3bae0adf569811"
|
||||||
"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2"
|
"checksum serde_urlencoded 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d48f9f99cd749a2de71d29da5f948de7f2764cc5a9d7f3c97e3514d4ee6eabf2"
|
||||||
"checksum serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0887a8e097a69559b56aa2526bf7aff7c3048cf627dff781f0b56a6001534593"
|
"checksum serde_yaml 0.8.8 (registry+https://github.com/rust-lang/crates.io-index)" = "0887a8e097a69559b56aa2526bf7aff7c3048cf627dff781f0b56a6001534593"
|
||||||
|
@ -3042,8 +3067,9 @@ dependencies = [
|
||||||
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
"checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac"
|
||||||
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
|
"checksum slab 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "5f9776d6b986f77b35c6cf846c11ad986ff128fe0b2b63a3628e3755e8d3102d"
|
||||||
"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
|
"checksum smallvec 0.6.7 (registry+https://github.com/rust-lang/crates.io-index)" = "b73ea3738b47563803ef814925e69be00799a8c07420be8b996f8e98fb2336db"
|
||||||
"checksum smithay-client-toolkit 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "4bfd1c912756e610ab598d60fb16adeb3b6745ac0b0a4a2cc1a6b9fa88111409"
|
"checksum smithay-client-toolkit 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "d858330eeed4efaf71c560555e2a6a0597d01b7d52685c3cc964ab1cc360f8c6"
|
||||||
"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
|
"checksum socket2 0.3.8 (registry+https://github.com/rust-lang/crates.io-index)" = "c4d11a52082057d87cb5caa31ad812f4504b97ab44732cd8359df2e9ff9f48e7"
|
||||||
|
"checksum spsc-buffer 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "be6c3f39c37a4283ee4b43d1311c828f2e1fb0541e76ea0cb1a2abd9ef2f5b3b"
|
||||||
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
"checksum stable_deref_trait 1.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dba1a27d3efae4351c8051072d619e3ade2820635c3958d826bfea39d59b54c8"
|
||||||
"checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1"
|
"checksum static_assertions 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "389ce475f424f267dbed6479cbd8f126c5e1afb053b0acdaa019c74305fc65d1"
|
||||||
"checksum stb_truetype 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71a7d260b43b6129a22dc341be18a231044ca67a48b7e32625f380cc5ec9ad70"
|
"checksum stb_truetype 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)" = "71a7d260b43b6129a22dc341be18a231044ca67a48b7e32625f380cc5ec9ad70"
|
||||||
|
@ -3099,6 +3125,7 @@ dependencies = [
|
||||||
"checksum wayland-sys 0.21.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a0931c24c91e4e56c1119e4137e237df2ccc3696df94f64b1e2f61982d89cc32"
|
"checksum wayland-sys 0.21.7 (registry+https://github.com/rust-lang/crates.io-index)" = "a0931c24c91e4e56c1119e4137e237df2ccc3696df94f64b1e2f61982d89cc32"
|
||||||
"checksum which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e84a603e7e0b1ce1aa1ee2b109c7be00155ce52df5081590d1ffb93f4f515cb2"
|
"checksum which 1.0.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e84a603e7e0b1ce1aa1ee2b109c7be00155ce52df5081590d1ffb93f4f515cb2"
|
||||||
"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb"
|
"checksum widestring 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb"
|
||||||
|
"checksum widestring 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "effc0e4ff8085673ea7b9b2e3c73f6bd4d118810c9009ed8f1e16bd96c331db6"
|
||||||
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
"checksum winapi 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)" = "167dc9d6949a9b857f3451275e911c3f44255842c1f7a76f33c55103a909087a"
|
||||||
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
"checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0"
|
||||||
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
"checksum winapi-build 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "2d315eee3b34aca4797b2da6b13ed88266e6d612562a0c46390af8299fc699bc"
|
||||||
|
|
|
@ -58,9 +58,12 @@ x11-dl = "2"
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
winpty = { path = "./winpty" }
|
winpty = { path = "./winpty" }
|
||||||
mio-named-pipes = "0.1"
|
mio-named-pipes = "0.1"
|
||||||
winapi = { version = "0.3.5", features = ["winuser", "synchapi", "roerrorapi", "winerror"]}
|
miow = "0.3"
|
||||||
|
winapi = { version = "0.3.5", features = ["impl-default", "winuser", "synchapi", "roerrorapi", "winerror", "wincon"]}
|
||||||
dunce = "0.1"
|
dunce = "0.1"
|
||||||
dirs = "1.0"
|
dirs = "1.0"
|
||||||
|
widestring = "0.4"
|
||||||
|
mio-anonymous-pipes = "0.1"
|
||||||
|
|
||||||
[target.'cfg(target_os = "macos")'.dependencies]
|
[target.'cfg(target_os = "macos")'.dependencies]
|
||||||
objc = "0.2.2"
|
objc = "0.2.2"
|
||||||
|
|
|
@ -283,6 +283,17 @@ shell:
|
||||||
#args:
|
#args:
|
||||||
# - --login
|
# - --login
|
||||||
|
|
||||||
|
# Windows 10 ConPTY backend
|
||||||
|
#
|
||||||
|
# This will enable better color support and may resolve other issues,
|
||||||
|
# however this API and its implementation is still young and so is
|
||||||
|
# disabled by default, as stability may not be as good as the winpty
|
||||||
|
# backend.
|
||||||
|
#
|
||||||
|
# Alacritty will fall back to the WinPTY automatically if the ConPTY
|
||||||
|
# backend cannot be initialized.
|
||||||
|
enable_experimental_conpty_backend: false
|
||||||
|
|
||||||
# Key bindings
|
# Key bindings
|
||||||
#
|
#
|
||||||
# Key bindings are specified as a list of objects. Each binding will specify
|
# Key bindings are specified as a list of objects. Each binding will specify
|
||||||
|
|
|
@ -541,6 +541,12 @@ pub struct Config {
|
||||||
// TODO: DEPRECATED
|
// TODO: DEPRECATED
|
||||||
#[serde(default, deserialize_with = "failure_default")]
|
#[serde(default, deserialize_with = "failure_default")]
|
||||||
unfocused_hollow_cursor: Option<bool>,
|
unfocused_hollow_cursor: Option<bool>,
|
||||||
|
|
||||||
|
/// Enable experimental conpty backend instead of using winpty.
|
||||||
|
/// Will only take effect on Windows 10 Oct 2018 and later.
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[serde(default, deserialize_with="failure_default")]
|
||||||
|
enable_experimental_conpty_backend: bool
|
||||||
}
|
}
|
||||||
|
|
||||||
fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result<Vec<T>, D::Error>
|
fn failure_default_vec<'a, D, T>(deserializer: D) -> ::std::result::Result<Vec<T>, D::Error>
|
||||||
|
@ -1709,6 +1715,13 @@ impl Config {
|
||||||
self.colors.cursor.cursor.map(|_| Color::Named(NamedColor::Cursor))
|
self.colors.cursor.cursor.map(|_| Color::Named(NamedColor::Cursor))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Enable experimental conpty backend (Windows only)
|
||||||
|
#[cfg(windows)]
|
||||||
|
#[inline]
|
||||||
|
pub fn enable_experimental_conpty_backend(&self) -> bool {
|
||||||
|
self.enable_experimental_conpty_backend
|
||||||
|
}
|
||||||
|
|
||||||
// Update the history size, used in ref tests
|
// Update the history size, used in ref tests
|
||||||
pub fn set_history(&mut self, history: u32) {
|
pub fn set_history(&mut self, history: u32) {
|
||||||
self.scrolling.history = history;
|
self.scrolling.history = history;
|
||||||
|
|
13
src/lib.rs
13
src/lib.rs
|
@ -20,19 +20,6 @@
|
||||||
#[macro_use] extern crate log;
|
#[macro_use] extern crate log;
|
||||||
#[macro_use] extern crate serde_derive;
|
#[macro_use] extern crate serde_derive;
|
||||||
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate mio_named_pipes;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate winapi;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate winpty;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate dunce;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate image;
|
|
||||||
#[cfg(windows)]
|
|
||||||
extern crate dirs;
|
|
||||||
|
|
||||||
#[cfg(target_os = "macos")]
|
#[cfg(target_os = "macos")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate objc;
|
extern crate objc;
|
||||||
|
|
|
@ -160,9 +160,9 @@ fn run(
|
||||||
// and we need to be able to resize the PTY from the main thread while the IO
|
// and we need to be able to resize the PTY from the main thread while the IO
|
||||||
// thread owns the EventedRW object.
|
// thread owns the EventedRW object.
|
||||||
#[cfg(windows)]
|
#[cfg(windows)]
|
||||||
let resize_handle = unsafe { &mut *pty.winpty.get() };
|
let mut resize_handle = pty.resize_handle();
|
||||||
#[cfg(not(windows))]
|
#[cfg(not(windows))]
|
||||||
let resize_handle = &mut pty.fd.as_raw_fd();
|
let mut resize_handle = pty.fd.as_raw_fd();
|
||||||
|
|
||||||
// Create the pseudoterminal I/O loop
|
// Create the pseudoterminal I/O loop
|
||||||
//
|
//
|
||||||
|
@ -239,7 +239,7 @@ fn run(
|
||||||
//
|
//
|
||||||
// The second argument is a list of types that want to be notified
|
// The second argument is a list of types that want to be notified
|
||||||
// of display size changes.
|
// of display size changes.
|
||||||
display.handle_resize(&mut terminal_lock, &config, &mut [resize_handle, &mut processor]);
|
display.handle_resize(&mut terminal_lock, &config, &mut [&mut resize_handle, &mut processor]);
|
||||||
|
|
||||||
drop(terminal_lock);
|
drop(terminal_lock);
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,303 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use super::{process_should_exit, Pty, HANDLE};
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::i16;
|
||||||
|
use std::mem;
|
||||||
|
use std::os::windows::io::IntoRawHandle;
|
||||||
|
use std::ptr;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use dunce::canonicalize;
|
||||||
|
use mio_anonymous_pipes::{EventedAnonRead, EventedAnonWrite};
|
||||||
|
use miow;
|
||||||
|
use widestring::U16CString;
|
||||||
|
use winapi::ctypes::c_void;
|
||||||
|
use winapi::shared::basetsd::{PSIZE_T, SIZE_T};
|
||||||
|
use winapi::shared::minwindef::{BYTE, DWORD};
|
||||||
|
use winapi::shared::ntdef::{HANDLE, HRESULT, LPCWSTR, LPWSTR};
|
||||||
|
use winapi::shared::winerror::S_OK;
|
||||||
|
use winapi::um::libloaderapi::{GetModuleHandleA, GetProcAddress};
|
||||||
|
use winapi::um::processthreadsapi::{
|
||||||
|
CreateProcessW, InitializeProcThreadAttributeList, UpdateProcThreadAttribute,
|
||||||
|
PROCESS_INFORMATION, STARTUPINFOW,
|
||||||
|
};
|
||||||
|
use winapi::um::winbase::{EXTENDED_STARTUPINFO_PRESENT, STARTUPINFOEXW};
|
||||||
|
use winapi::um::wincon::COORD;
|
||||||
|
|
||||||
|
use crate::cli::Options;
|
||||||
|
use crate::config::{Config, Shell};
|
||||||
|
use crate::display::OnResize;
|
||||||
|
use crate::term::SizeInfo;
|
||||||
|
|
||||||
|
// This will be merged into winapi as PR #699
|
||||||
|
// TODO: Use the winapi definition directly after that.
|
||||||
|
pub type HPCON = *mut c_void;
|
||||||
|
|
||||||
|
/// Dynamically-loaded Pseudoconsole API from kernel32.dll
|
||||||
|
///
|
||||||
|
/// The field names are deliberately PascalCase as this matches
|
||||||
|
/// the defined symbols in kernel32 and also is the convention
|
||||||
|
/// that the `winapi` crate follows.
|
||||||
|
#[allow(non_snake_case)]
|
||||||
|
struct ConptyApi {
|
||||||
|
CreatePseudoConsole:
|
||||||
|
unsafe extern "system" fn(COORD, HANDLE, HANDLE, DWORD, *mut HPCON) -> HRESULT,
|
||||||
|
ResizePseudoConsole: unsafe extern "system" fn(HPCON, COORD) -> HRESULT,
|
||||||
|
ClosePseudoConsole: unsafe extern "system" fn(HPCON) -> HRESULT,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ConptyApi {
|
||||||
|
/// Load the API or None if it cannot be found.
|
||||||
|
pub fn new() -> Option<Self> {
|
||||||
|
// Unsafe because windows API calls
|
||||||
|
unsafe {
|
||||||
|
let hmodule = GetModuleHandleA("kernel32\0".as_ptr() as _);
|
||||||
|
assert!(!hmodule.is_null());
|
||||||
|
|
||||||
|
let cpc = GetProcAddress(hmodule, "CreatePseudoConsole\0".as_ptr() as _);
|
||||||
|
let rpc = GetProcAddress(hmodule, "ResizePseudoConsole\0".as_ptr() as _);
|
||||||
|
let clpc = GetProcAddress(hmodule, "ClosePseudoConsole\0".as_ptr() as _);
|
||||||
|
|
||||||
|
if cpc.is_null() || rpc.is_null() || clpc.is_null() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(Self {
|
||||||
|
CreatePseudoConsole: mem::transmute(cpc),
|
||||||
|
ResizePseudoConsole: mem::transmute(rpc),
|
||||||
|
ClosePseudoConsole: mem::transmute(clpc),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// RAII Pseudoconsole
|
||||||
|
pub struct Conpty {
|
||||||
|
pub handle: HPCON,
|
||||||
|
api: ConptyApi,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle can be cloned freely and moved between threads.
|
||||||
|
pub type ConptyHandle = Arc<Conpty>;
|
||||||
|
|
||||||
|
impl Drop for Conpty {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
// The pseusdoconsole might already have been closed by the console process exiting.
|
||||||
|
// ClosePseudoConsole will fail with error code 1 in that case.
|
||||||
|
//
|
||||||
|
// This check should be sufficient to avoid that.
|
||||||
|
if !process_should_exit() {
|
||||||
|
let result = unsafe { (self.api.ClosePseudoConsole)(self.handle) };
|
||||||
|
|
||||||
|
// As noted above, if the pseudoconsole is already closed then
|
||||||
|
// ClosePseudoConsole will fail with the error code 1.
|
||||||
|
// (This was not in the MSDN docs as of Nov 2018.)
|
||||||
|
//
|
||||||
|
// If ClosePseudoConsole is successful then result is S_OK.
|
||||||
|
assert!(result == S_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The Conpty API can be accessed from multiple threads.
|
||||||
|
unsafe impl Send for Conpty {}
|
||||||
|
unsafe impl Sync for Conpty {}
|
||||||
|
|
||||||
|
pub fn new<'a>(
|
||||||
|
config: &Config,
|
||||||
|
options: &Options,
|
||||||
|
size: &SizeInfo,
|
||||||
|
_window_id: Option<usize>,
|
||||||
|
) -> Option<Pty<'a>> {
|
||||||
|
if !config.enable_experimental_conpty_backend() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
let api = ConptyApi::new()?;
|
||||||
|
|
||||||
|
let mut pty_handle = 0 as HPCON;
|
||||||
|
|
||||||
|
// Passing 0 as the size parameter allows the "system default" buffer
|
||||||
|
// size to be used. There may be small performance and memory advantages
|
||||||
|
// to be gained by tuning this in the future, but it's likely a reasonable
|
||||||
|
// start point.
|
||||||
|
let (conout, conout_pty_handle) = miow::pipe::anonymous(0).unwrap();
|
||||||
|
let (conin_pty_handle, conin) = miow::pipe::anonymous(0).unwrap();
|
||||||
|
|
||||||
|
let coord =
|
||||||
|
coord_from_sizeinfo(size).expect("Overflow when creating initial size on pseudoconsole");
|
||||||
|
|
||||||
|
// Create the Pseudo Console, using the pipes
|
||||||
|
let result = unsafe {
|
||||||
|
(api.CreatePseudoConsole)(
|
||||||
|
coord,
|
||||||
|
conin_pty_handle.into_raw_handle(),
|
||||||
|
conout_pty_handle.into_raw_handle(),
|
||||||
|
0,
|
||||||
|
&mut pty_handle as *mut HPCON,
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
assert!(result == S_OK);
|
||||||
|
|
||||||
|
let mut success;
|
||||||
|
|
||||||
|
// Prepare child process startup info
|
||||||
|
|
||||||
|
let mut size: SIZE_T = 0;
|
||||||
|
|
||||||
|
let mut startup_info_ex: STARTUPINFOEXW = Default::default();
|
||||||
|
startup_info_ex.StartupInfo.cb = mem::size_of::<STARTUPINFOEXW>() as u32;
|
||||||
|
|
||||||
|
// Create the appropriately sized thread attribute list.
|
||||||
|
unsafe {
|
||||||
|
success =
|
||||||
|
InitializeProcThreadAttributeList(ptr::null_mut(), 1, 0, &mut size as PSIZE_T) > 0;
|
||||||
|
|
||||||
|
// This call was expected to return false.
|
||||||
|
assert!(!success);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut attr_list: Box<[BYTE]> = vec![0; size].into_boxed_slice();
|
||||||
|
|
||||||
|
// Set startup info's attribute list & initialize it
|
||||||
|
//
|
||||||
|
// Lint failure is spurious; it's because winapi's definition of PROC_THREAD_ATTRIBUTE_LIST
|
||||||
|
// implies it is one pointer in size (32 or 64 bits) but really this is just a dummy value.
|
||||||
|
// Casting a *mut u8 (pointer to 8 bit type) might therefore not be aligned correctly in
|
||||||
|
// the compiler's eyes.
|
||||||
|
#[allow(clippy::cast_ptr_alignment)]
|
||||||
|
{
|
||||||
|
startup_info_ex.lpAttributeList = attr_list.as_mut_ptr() as _;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
success = InitializeProcThreadAttributeList(
|
||||||
|
startup_info_ex.lpAttributeList,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
&mut size as PSIZE_T,
|
||||||
|
) > 0;
|
||||||
|
|
||||||
|
assert!(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set thread attribute list's Pseudo Console to the specified ConPTY
|
||||||
|
unsafe {
|
||||||
|
success = UpdateProcThreadAttribute(
|
||||||
|
startup_info_ex.lpAttributeList,
|
||||||
|
0,
|
||||||
|
22 | 0x0002_0000, // PROC_THREAD_ATTRIBUTE_PSEUDOCONSOLE
|
||||||
|
pty_handle,
|
||||||
|
mem::size_of::<HPCON>(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
) > 0;
|
||||||
|
|
||||||
|
assert!(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get process commandline
|
||||||
|
let default_shell = &Shell::new(env::var("COMSPEC").unwrap_or_else(|_| "cmd".into()));
|
||||||
|
let shell = config.shell().unwrap_or(default_shell);
|
||||||
|
let initial_command = options.command().unwrap_or(shell);
|
||||||
|
let mut cmdline = initial_command.args().to_vec();
|
||||||
|
cmdline.insert(0, initial_command.program().into());
|
||||||
|
|
||||||
|
// Warning, here be borrow hell
|
||||||
|
let cwd = options
|
||||||
|
.working_dir
|
||||||
|
.as_ref()
|
||||||
|
.map(|dir| canonicalize(dir).unwrap());
|
||||||
|
let cwd = cwd.as_ref().map(|dir| dir.to_str().unwrap());
|
||||||
|
|
||||||
|
// Create the client application, using startup info containing ConPTY info
|
||||||
|
let cmdline = U16CString::from_str(&cmdline.join(" ")).unwrap().into_raw();
|
||||||
|
let cwd = cwd.map(|s| U16CString::from_str(&s).unwrap());
|
||||||
|
let cwd_ptr = match &cwd {
|
||||||
|
Some(b) => b.as_ptr() as LPCWSTR,
|
||||||
|
None => ptr::null(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut proc_info: PROCESS_INFORMATION = Default::default();
|
||||||
|
unsafe {
|
||||||
|
success = CreateProcessW(
|
||||||
|
ptr::null(),
|
||||||
|
cmdline as LPWSTR,
|
||||||
|
ptr::null_mut(),
|
||||||
|
ptr::null_mut(),
|
||||||
|
true as i32,
|
||||||
|
EXTENDED_STARTUPINFO_PRESENT,
|
||||||
|
ptr::null_mut(),
|
||||||
|
cwd_ptr,
|
||||||
|
&mut startup_info_ex.StartupInfo as *mut STARTUPINFOW,
|
||||||
|
&mut proc_info as *mut PROCESS_INFORMATION,
|
||||||
|
) > 0;
|
||||||
|
|
||||||
|
assert!(success);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Recover raw memory to cmdline so it can be freed
|
||||||
|
unsafe {
|
||||||
|
U16CString::from_raw(cmdline);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store handle to console
|
||||||
|
unsafe {
|
||||||
|
HANDLE = proc_info.hProcess;
|
||||||
|
}
|
||||||
|
|
||||||
|
let conin = EventedAnonWrite::new(conin);
|
||||||
|
let conout = EventedAnonRead::new(conout);
|
||||||
|
|
||||||
|
let agent = Conpty {
|
||||||
|
handle: pty_handle,
|
||||||
|
api,
|
||||||
|
};
|
||||||
|
|
||||||
|
Some(Pty {
|
||||||
|
handle: super::PtyHandle::Conpty(ConptyHandle::new(agent)),
|
||||||
|
conout: super::EventedReadablePipe::Anonymous(conout),
|
||||||
|
conin: super::EventedWritablePipe::Anonymous(conin),
|
||||||
|
read_token: 0.into(),
|
||||||
|
write_token: 0.into(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl OnResize for ConptyHandle {
|
||||||
|
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
||||||
|
if let Some(coord) = coord_from_sizeinfo(sizeinfo) {
|
||||||
|
let result = unsafe { (self.api.ResizePseudoConsole)(self.handle, coord) };
|
||||||
|
assert!(result == S_OK);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Helper to build a COORD from a SizeInfo, returing None in overflow cases.
|
||||||
|
fn coord_from_sizeinfo(sizeinfo: &SizeInfo) -> Option<COORD> {
|
||||||
|
let cols = sizeinfo.cols().0;
|
||||||
|
let lines = sizeinfo.lines().0;
|
||||||
|
|
||||||
|
if cols <= i16::MAX as usize && lines <= i16::MAX as usize {
|
||||||
|
Some(COORD {
|
||||||
|
X: sizeinfo.cols().0 as i16,
|
||||||
|
Y: sizeinfo.lines().0 as i16,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,334 @@
|
||||||
|
// Copyright 2016 Joe Wilm, The Alacritty Project Contributors
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
// you may not use this file except in compliance with the License.
|
||||||
|
// You may obtain a copy of the License at
|
||||||
|
//
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
//
|
||||||
|
// Unless required by applicable law or agreed to in writing, software
|
||||||
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
// See the License for the specific language governing permissions and
|
||||||
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::io::{self, Read, Write};
|
||||||
|
use std::os::raw::c_void;
|
||||||
|
|
||||||
|
use mio::{self, Evented, Poll, PollOpt, Ready, Token};
|
||||||
|
use mio_anonymous_pipes::{EventedAnonRead, EventedAnonWrite};
|
||||||
|
use mio_named_pipes::NamedPipe;
|
||||||
|
|
||||||
|
use winapi::shared::winerror::WAIT_TIMEOUT;
|
||||||
|
use winapi::um::synchapi::WaitForSingleObject;
|
||||||
|
use winapi::um::winbase::WAIT_OBJECT_0;
|
||||||
|
|
||||||
|
use crate::cli::Options;
|
||||||
|
use crate::config::Config;
|
||||||
|
use crate::display::OnResize;
|
||||||
|
use crate::term::SizeInfo;
|
||||||
|
use crate::tty::EventedReadWrite;
|
||||||
|
|
||||||
|
mod conpty;
|
||||||
|
mod winpty;
|
||||||
|
|
||||||
|
/// Handle to the winpty agent or conpty process. Required so we know when it closes.
|
||||||
|
static mut HANDLE: *mut c_void = 0usize as *mut c_void;
|
||||||
|
|
||||||
|
pub fn process_should_exit() -> bool {
|
||||||
|
unsafe {
|
||||||
|
match WaitForSingleObject(HANDLE, 0) {
|
||||||
|
// Process has exited
|
||||||
|
WAIT_OBJECT_0 => {
|
||||||
|
info!("wait_object_0");
|
||||||
|
true
|
||||||
|
}
|
||||||
|
// Reached timeout of 0, process has not exited
|
||||||
|
WAIT_TIMEOUT => false,
|
||||||
|
// Error checking process, winpty gave us a bad agent handle?
|
||||||
|
_ => {
|
||||||
|
info!("Bad exit: {}", ::std::io::Error::last_os_error());
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone)]
|
||||||
|
pub enum PtyHandle<'a> {
|
||||||
|
Winpty(winpty::WinptyHandle<'a>),
|
||||||
|
Conpty(conpty::ConptyHandle),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Pty<'a> {
|
||||||
|
handle: PtyHandle<'a>,
|
||||||
|
// TODO: It's on the roadmap for the Conpty API to support Overlapped I/O.
|
||||||
|
// See https://github.com/Microsoft/console/issues/262
|
||||||
|
// When support for that lands then it should be possible to use
|
||||||
|
// NamedPipe for the conout and conin handles
|
||||||
|
conout: EventedReadablePipe,
|
||||||
|
conin: EventedWritablePipe,
|
||||||
|
read_token: mio::Token,
|
||||||
|
write_token: mio::Token,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Pty<'a> {
|
||||||
|
pub fn resize_handle(&self) -> impl OnResize + 'a {
|
||||||
|
self.handle.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn new<'a>(
|
||||||
|
config: &Config,
|
||||||
|
options: &Options,
|
||||||
|
size: &SizeInfo,
|
||||||
|
window_id: Option<usize>,
|
||||||
|
) -> Pty<'a> {
|
||||||
|
if let Some(pty) = conpty::new(config, options, size, window_id) {
|
||||||
|
info!("Using Conpty agent.");
|
||||||
|
pty
|
||||||
|
} else {
|
||||||
|
info!("Using Winpty agent.");
|
||||||
|
winpty::new(config, options, size, window_id)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: The ConPTY API curently must use synchronous pipes as the input
|
||||||
|
// and output handles. This has led to the need to support two different
|
||||||
|
// types of pipe.
|
||||||
|
//
|
||||||
|
// When https://github.com/Microsoft/console/issues/262 lands then the
|
||||||
|
// Anonymous variant of this enum can be removed from the codebase and
|
||||||
|
// everything can just use NamedPipe.
|
||||||
|
pub enum EventedReadablePipe {
|
||||||
|
Anonymous(EventedAnonRead),
|
||||||
|
Named(NamedPipe),
|
||||||
|
}
|
||||||
|
|
||||||
|
pub enum EventedWritablePipe {
|
||||||
|
Anonymous(EventedAnonWrite),
|
||||||
|
Named(NamedPipe),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Evented for EventedReadablePipe {
|
||||||
|
fn register(
|
||||||
|
&self,
|
||||||
|
poll: &Poll,
|
||||||
|
token: Token,
|
||||||
|
interest: Ready,
|
||||||
|
opts: PollOpt,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedReadablePipe::Anonymous(p) => p.register(poll, token, interest, opts),
|
||||||
|
EventedReadablePipe::Named(p) => p.register(poll, token, interest, opts),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reregister(
|
||||||
|
&self,
|
||||||
|
poll: &Poll,
|
||||||
|
token: Token,
|
||||||
|
interest: Ready,
|
||||||
|
opts: PollOpt,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedReadablePipe::Anonymous(p) => p.reregister(poll, token, interest, opts),
|
||||||
|
EventedReadablePipe::Named(p) => p.reregister(poll, token, interest, opts),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deregister(&self, poll: &Poll) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedReadablePipe::Anonymous(p) => p.deregister(poll),
|
||||||
|
EventedReadablePipe::Named(p) => p.deregister(poll),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Read for EventedReadablePipe {
|
||||||
|
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
EventedReadablePipe::Anonymous(p) => p.read(buf),
|
||||||
|
EventedReadablePipe::Named(p) => p.read(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Evented for EventedWritablePipe {
|
||||||
|
fn register(
|
||||||
|
&self,
|
||||||
|
poll: &Poll,
|
||||||
|
token: Token,
|
||||||
|
interest: Ready,
|
||||||
|
opts: PollOpt,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedWritablePipe::Anonymous(p) => p.register(poll, token, interest, opts),
|
||||||
|
EventedWritablePipe::Named(p) => p.register(poll, token, interest, opts),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reregister(
|
||||||
|
&self,
|
||||||
|
poll: &Poll,
|
||||||
|
token: Token,
|
||||||
|
interest: Ready,
|
||||||
|
opts: PollOpt,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedWritablePipe::Anonymous(p) => p.reregister(poll, token, interest, opts),
|
||||||
|
EventedWritablePipe::Named(p) => p.reregister(poll, token, interest, opts),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn deregister(&self, poll: &Poll) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedWritablePipe::Anonymous(p) => p.deregister(poll),
|
||||||
|
EventedWritablePipe::Named(p) => p.deregister(poll),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Write for EventedWritablePipe {
|
||||||
|
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
|
||||||
|
match self {
|
||||||
|
EventedWritablePipe::Anonymous(p) => p.write(buf),
|
||||||
|
EventedWritablePipe::Named(p) => p.write(buf),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn flush(&mut self) -> io::Result<()> {
|
||||||
|
match self {
|
||||||
|
EventedWritablePipe::Anonymous(p) => p.flush(),
|
||||||
|
EventedWritablePipe::Named(p) => p.flush(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> OnResize for PtyHandle<'a> {
|
||||||
|
fn on_resize(&mut self, sizeinfo: &SizeInfo) {
|
||||||
|
match self {
|
||||||
|
PtyHandle::Winpty(w) => w.winpty_mut().on_resize(sizeinfo),
|
||||||
|
PtyHandle::Conpty(c) => {
|
||||||
|
let mut handle = c.clone();
|
||||||
|
handle.on_resize(sizeinfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EventedReadWrite for Pty<'a> {
|
||||||
|
type Reader = EventedReadablePipe;
|
||||||
|
type Writer = EventedWritablePipe;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn register(
|
||||||
|
&mut self,
|
||||||
|
poll: &mio::Poll,
|
||||||
|
token: &mut dyn Iterator<Item = &usize>,
|
||||||
|
interest: mio::Ready,
|
||||||
|
poll_opts: mio::PollOpt,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
self.read_token = (*token.next().unwrap()).into();
|
||||||
|
self.write_token = (*token.next().unwrap()).into();
|
||||||
|
|
||||||
|
if interest.is_readable() {
|
||||||
|
poll.register(
|
||||||
|
&self.conout,
|
||||||
|
self.read_token,
|
||||||
|
mio::Ready::readable(),
|
||||||
|
poll_opts,
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
poll.register(
|
||||||
|
&self.conout,
|
||||||
|
self.read_token,
|
||||||
|
mio::Ready::empty(),
|
||||||
|
poll_opts,
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
if interest.is_writable() {
|
||||||
|
poll.register(
|
||||||
|
&self.conin,
|
||||||
|
self.write_token,
|
||||||
|
mio::Ready::writable(),
|
||||||
|
poll_opts,
|
||||||
|
)?
|
||||||
|
} else {
|
||||||
|
poll.register(
|
||||||
|
&self.conin,
|
||||||
|
self.write_token,
|
||||||
|
mio::Ready::empty(),
|
||||||
|
poll_opts,
|
||||||
|
)?
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn reregister(
|
||||||
|
&mut self,
|
||||||
|
poll: &mio::Poll,
|
||||||
|
interest: mio::Ready,
|
||||||
|
poll_opts: mio::PollOpt,
|
||||||
|
) -> io::Result<()> {
|
||||||
|
if interest.is_readable() {
|
||||||
|
poll.reregister(
|
||||||
|
&self.conout,
|
||||||
|
self.read_token,
|
||||||
|
mio::Ready::readable(),
|
||||||
|
poll_opts,
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
poll.reregister(
|
||||||
|
&self.conout,
|
||||||
|
self.read_token,
|
||||||
|
mio::Ready::empty(),
|
||||||
|
poll_opts,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
if interest.is_writable() {
|
||||||
|
poll.reregister(
|
||||||
|
&self.conin,
|
||||||
|
self.write_token,
|
||||||
|
mio::Ready::writable(),
|
||||||
|
poll_opts,
|
||||||
|
)?;
|
||||||
|
} else {
|
||||||
|
poll.reregister(
|
||||||
|
&self.conin,
|
||||||
|
self.write_token,
|
||||||
|
mio::Ready::empty(),
|
||||||
|
poll_opts,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn deregister(&mut self, poll: &mio::Poll) -> io::Result<()> {
|
||||||
|
poll.deregister(&self.conout)?;
|
||||||
|
poll.deregister(&self.conin)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn reader(&mut self) -> &mut Self::Reader {
|
||||||
|
&mut self.conout
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn read_token(&self) -> mio::Token {
|
||||||
|
self.read_token
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn writer(&mut self) -> &mut Self::Writer {
|
||||||
|
&mut self.conin
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn write_token(&self) -> mio::Token {
|
||||||
|
self.write_token
|
||||||
|
}
|
||||||
|
}
|
|
@ -12,73 +12,78 @@
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use super::{Pty, HANDLE};
|
||||||
|
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::fs::OpenOptions;
|
use std::fs::OpenOptions;
|
||||||
use std::os::raw::c_void;
|
|
||||||
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
|
use std::os::windows::io::{FromRawHandle, IntoRawHandle};
|
||||||
use std::os::windows::fs::OpenOptionsExt;
|
use std::os::windows::fs::OpenOptionsExt;
|
||||||
use std::env;
|
use std::env;
|
||||||
use std::cell::UnsafeCell;
|
use std::sync::Arc;
|
||||||
use std::u16;
|
use std::u16;
|
||||||
|
|
||||||
use dunce::canonicalize;
|
use dunce::canonicalize;
|
||||||
use mio;
|
|
||||||
use mio::Evented;
|
|
||||||
use mio_named_pipes::NamedPipe;
|
use mio_named_pipes::NamedPipe;
|
||||||
use winapi::um::synchapi::WaitForSingleObject;
|
use winapi::um::winbase::FILE_FLAG_OVERLAPPED;
|
||||||
use winapi::um::winbase::{WAIT_OBJECT_0, FILE_FLAG_OVERLAPPED};
|
|
||||||
use winapi::shared::winerror::WAIT_TIMEOUT;
|
|
||||||
use winpty::{ConfigFlags, MouseMode, SpawnConfig, SpawnFlags, Winpty};
|
use winpty::{ConfigFlags, MouseMode, SpawnConfig, SpawnFlags, Winpty};
|
||||||
use winpty::Config as WinptyConfig;
|
use winpty::Config as WinptyConfig;
|
||||||
|
|
||||||
use crate::config::{Config, Shell};
|
use crate::config::{Config, Shell};
|
||||||
use crate::display::OnResize;
|
use crate::display::OnResize;
|
||||||
use crate::cli::Options;
|
use crate::cli::Options;
|
||||||
use crate::tty::EventedReadWrite;
|
|
||||||
use crate::term::SizeInfo;
|
use crate::term::SizeInfo;
|
||||||
|
|
||||||
/// Handle to the winpty agent process. Required so we know when it closes.
|
// We store a raw pointer because we need mutable access to call
|
||||||
static mut HANDLE: *mut c_void = 0usize as *mut c_void;
|
// on_resize from a separate thread. Winpty internally uses a mutex
|
||||||
|
// so this is safe, despite outwards appearance.
|
||||||
|
pub struct Agent<'a> {
|
||||||
|
winpty: *mut Winpty<'a>
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Handle can be cloned freely and moved between threads.
|
||||||
|
pub type WinptyHandle<'a> = Arc<Agent<'a>>;
|
||||||
|
|
||||||
|
// Because Winpty has a mutex, we can do this.
|
||||||
|
unsafe impl<'a> Send for Agent<'a> {}
|
||||||
|
unsafe impl<'a> Sync for Agent<'a> {}
|
||||||
|
|
||||||
|
impl<'a> Agent<'a> {
|
||||||
|
pub fn new(winpty: Winpty<'a>) -> Self {
|
||||||
|
Self {
|
||||||
|
winpty: Box::into_raw(Box::new(winpty))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get immutable access to Winpty.
|
||||||
|
pub fn winpty(&self) -> &Winpty<'a> {
|
||||||
|
unsafe {&*self.winpty}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get mutable access to Winpty.
|
||||||
|
/// Can offer internal mutability like this because Winpty uses
|
||||||
|
/// a mutex internally.
|
||||||
|
pub fn winpty_mut(&self) -> &mut Winpty<'a> {
|
||||||
|
unsafe {&mut *self.winpty}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Drop for Agent<'a> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe { Box::from_raw(self.winpty); }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// How long the winpty agent should wait for any RPC request
|
/// How long the winpty agent should wait for any RPC request
|
||||||
/// This is a placeholder value until we see how often long responses happen
|
/// This is a placeholder value until we see how often long responses happen
|
||||||
const AGENT_TIMEOUT: u32 = 10000;
|
const AGENT_TIMEOUT: u32 = 10000;
|
||||||
|
|
||||||
pub fn process_should_exit() -> bool {
|
|
||||||
unsafe {
|
|
||||||
match WaitForSingleObject(HANDLE, 0) {
|
|
||||||
// Process has exited
|
|
||||||
WAIT_OBJECT_0 => {
|
|
||||||
info!("wait_object_0");
|
|
||||||
true
|
|
||||||
}
|
|
||||||
// Reached timeout of 0, process has not exited
|
|
||||||
WAIT_TIMEOUT => false,
|
|
||||||
// Error checking process, winpty gave us a bad agent handle?
|
|
||||||
_ => {
|
|
||||||
info!("Bad exit: {}", ::std::io::Error::last_os_error());
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub struct Pty<'a, R: io::Read + Evented + Send, W: io::Write + Evented + Send> {
|
|
||||||
// TODO: Provide methods for accessing this safely
|
|
||||||
pub winpty: UnsafeCell<Winpty<'a>>,
|
|
||||||
|
|
||||||
conout: R,
|
|
||||||
conin: W,
|
|
||||||
read_token: mio::Token,
|
|
||||||
write_token: mio::Token,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn new<'a>(
|
pub fn new<'a>(
|
||||||
config: &Config,
|
config: &Config,
|
||||||
options: &Options,
|
options: &Options,
|
||||||
size: &SizeInfo,
|
size: &SizeInfo,
|
||||||
_window_id: Option<usize>,
|
_window_id: Option<usize>,
|
||||||
) -> Pty<'a, NamedPipe, NamedPipe> {
|
) -> Pty<'a> {
|
||||||
// Create config
|
// Create config
|
||||||
let mut wconfig = WinptyConfig::new(ConfigFlags::empty()).unwrap();
|
let mut wconfig = WinptyConfig::new(ConfigFlags::empty()).unwrap();
|
||||||
|
|
||||||
|
@ -155,123 +160,14 @@ pub fn new<'a>(
|
||||||
HANDLE = winpty.raw_handle();
|
HANDLE = winpty.raw_handle();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let agent = Agent::new(winpty);
|
||||||
|
|
||||||
Pty {
|
Pty {
|
||||||
winpty: UnsafeCell::new(winpty),
|
handle: super::PtyHandle::Winpty(WinptyHandle::new(agent)),
|
||||||
conout: conout_pipe,
|
conout: super::EventedReadablePipe::Named(conout_pipe),
|
||||||
conin: conin_pipe,
|
conin: super::EventedWritablePipe::Named(conin_pipe),
|
||||||
// Placeholder tokens that are overwritten
|
|
||||||
read_token: 0.into(),
|
read_token: 0.into(),
|
||||||
write_token: 0.into(),
|
write_token: 0.into()
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> EventedReadWrite for Pty<'a, NamedPipe, NamedPipe> {
|
|
||||||
type Reader = NamedPipe;
|
|
||||||
type Writer = NamedPipe;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn register(
|
|
||||||
&mut self,
|
|
||||||
poll: &mio::Poll,
|
|
||||||
token: &mut Iterator<Item = &usize>,
|
|
||||||
interest: mio::Ready,
|
|
||||||
poll_opts: mio::PollOpt,
|
|
||||||
) -> io::Result<()> {
|
|
||||||
self.read_token = (*token.next().unwrap()).into();
|
|
||||||
self.write_token = (*token.next().unwrap()).into();
|
|
||||||
if interest.is_readable() {
|
|
||||||
poll.register(
|
|
||||||
&self.conout,
|
|
||||||
self.read_token,
|
|
||||||
mio::Ready::readable(),
|
|
||||||
poll_opts,
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
poll.register(
|
|
||||||
&self.conout,
|
|
||||||
self.read_token,
|
|
||||||
mio::Ready::empty(),
|
|
||||||
poll_opts,
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
if interest.is_writable() {
|
|
||||||
poll.register(
|
|
||||||
&self.conin,
|
|
||||||
self.write_token,
|
|
||||||
mio::Ready::writable(),
|
|
||||||
poll_opts,
|
|
||||||
)?
|
|
||||||
} else {
|
|
||||||
poll.register(
|
|
||||||
&self.conin,
|
|
||||||
self.write_token,
|
|
||||||
mio::Ready::empty(),
|
|
||||||
poll_opts,
|
|
||||||
)?
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn reregister(&mut self, poll: &mio::Poll, interest: mio::Ready, poll_opts: mio::PollOpt) -> io::Result<()> {
|
|
||||||
if interest.is_readable() {
|
|
||||||
poll.reregister(
|
|
||||||
&self.conout,
|
|
||||||
self.read_token,
|
|
||||||
mio::Ready::readable(),
|
|
||||||
poll_opts,
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
poll.reregister(
|
|
||||||
&self.conout,
|
|
||||||
self.read_token,
|
|
||||||
mio::Ready::empty(),
|
|
||||||
poll_opts,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
if interest.is_writable() {
|
|
||||||
poll.reregister(
|
|
||||||
&self.conin,
|
|
||||||
self.write_token,
|
|
||||||
mio::Ready::writable(),
|
|
||||||
poll_opts,
|
|
||||||
)?;
|
|
||||||
} else {
|
|
||||||
poll.reregister(
|
|
||||||
&self.conin,
|
|
||||||
self.write_token,
|
|
||||||
mio::Ready::empty(),
|
|
||||||
poll_opts,
|
|
||||||
)?;
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn deregister(&mut self, poll: &mio::Poll) -> io::Result<()> {
|
|
||||||
poll.deregister(&self.conout)?;
|
|
||||||
poll.deregister(&self.conin)?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn reader(&mut self) -> &mut NamedPipe {
|
|
||||||
&mut self.conout
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn read_token(&self) -> mio::Token {
|
|
||||||
self.read_token
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn writer(&mut self) -> &mut NamedPipe {
|
|
||||||
&mut self.conin
|
|
||||||
}
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn write_token(&self) -> mio::Token {
|
|
||||||
self.write_token
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue