gpui: Handle null string pointer in window::insert_text
(#12446)
`[NSString UTF8String]` sometimes returns null (it's documented as such), and when it does, zed crashes in `window::insert_text`. I'm running into this sometimes when using alt-d to delete forward. It usually only happens with multiple cursors, but sometimes with a single cursor. It *might* only happen when using the "Unicode Hex Input" keyboard 'Input Source' (which I started using to avoid entering weird characters in zed when using emacs meta keybindings that I haven't defined in zed). When using the US English input source, alt-d always results in a call to `insert_text`. When using the Unicode Hex Input source it usually doesn't, but when it does `text.UTF8String()` returns null. `text` isn't null. `[text length]` returns 1. `[text characterAtIndex: 0]` seems to always return `56797` (an undefined utf-16 codepoint). Release Notes: - Fixed crash on mac when deleting with alt-d
This commit is contained in:
parent
344e5e1cf2
commit
be2df79d5c
3 changed files with 33 additions and 23 deletions
|
@ -29,7 +29,10 @@ use cocoa::{
|
||||||
};
|
};
|
||||||
|
|
||||||
use objc::runtime::{BOOL, NO, YES};
|
use objc::runtime::{BOOL, NO, YES};
|
||||||
use std::ops::Range;
|
use std::{
|
||||||
|
ffi::{c_char, CStr},
|
||||||
|
ops::Range,
|
||||||
|
};
|
||||||
|
|
||||||
pub(crate) use dispatcher::*;
|
pub(crate) use dispatcher::*;
|
||||||
pub(crate) use display::*;
|
pub(crate) use display::*;
|
||||||
|
@ -52,6 +55,21 @@ impl BoolExt for bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
trait NSStringExt {
|
||||||
|
unsafe fn to_str(&self) -> &str;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NSStringExt for id {
|
||||||
|
unsafe fn to_str(&self) -> &str {
|
||||||
|
let cstr = self.UTF8String();
|
||||||
|
if cstr.is_null() {
|
||||||
|
""
|
||||||
|
} else {
|
||||||
|
CStr::from_ptr(cstr as *mut c_char).to_str().unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[derive(Copy, Clone, Debug)]
|
#[derive(Copy, Clone, Debug)]
|
||||||
struct NSRange {
|
struct NSRange {
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
use crate::{
|
use crate::{
|
||||||
point, px, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers, ModifiersChangedEvent, MouseButton,
|
platform::mac::NSStringExt, point, px, KeyDownEvent, KeyUpEvent, Keystroke, Modifiers,
|
||||||
MouseDownEvent, MouseExitEvent, MouseMoveEvent, MouseUpEvent, NavigationDirection, Pixels,
|
ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseExitEvent, MouseMoveEvent,
|
||||||
PlatformInput, ScrollDelta, ScrollWheelEvent, TouchPhase,
|
MouseUpEvent, NavigationDirection, Pixels, PlatformInput, ScrollDelta, ScrollWheelEvent,
|
||||||
|
TouchPhase,
|
||||||
};
|
};
|
||||||
use cocoa::{
|
use cocoa::{
|
||||||
appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType},
|
appkit::{NSEvent, NSEventModifierFlags, NSEventPhase, NSEventType},
|
||||||
base::{id, YES},
|
base::{id, YES},
|
||||||
foundation::NSString as _,
|
|
||||||
};
|
};
|
||||||
use core_graphics::{
|
use core_graphics::{
|
||||||
event::{CGEvent, CGEventFlags, CGKeyCode},
|
event::{CGEvent, CGEventFlags, CGKeyCode},
|
||||||
|
@ -15,7 +15,7 @@ use core_graphics::{
|
||||||
use ctor::ctor;
|
use ctor::ctor;
|
||||||
use metal::foreign_types::ForeignType as _;
|
use metal::foreign_types::ForeignType as _;
|
||||||
use objc::{class, msg_send, sel, sel_impl};
|
use objc::{class, msg_send, sel, sel_impl};
|
||||||
use std::{borrow::Cow, ffi::CStr, mem, os::raw::c_char, ptr};
|
use std::{borrow::Cow, mem, ptr};
|
||||||
|
|
||||||
const BACKSPACE_KEY: u16 = 0x7f;
|
const BACKSPACE_KEY: u16 = 0x7f;
|
||||||
const SPACE_KEY: u16 = b' ' as u16;
|
const SPACE_KEY: u16 = b' ' as u16;
|
||||||
|
@ -243,11 +243,10 @@ impl PlatformInput {
|
||||||
unsafe fn parse_keystroke(native_event: id) -> Keystroke {
|
unsafe fn parse_keystroke(native_event: id) -> Keystroke {
|
||||||
use cocoa::appkit::*;
|
use cocoa::appkit::*;
|
||||||
|
|
||||||
let mut chars_ignoring_modifiers =
|
let mut chars_ignoring_modifiers = native_event
|
||||||
CStr::from_ptr(native_event.charactersIgnoringModifiers().UTF8String() as *mut c_char)
|
.charactersIgnoringModifiers()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap()
|
.to_string();
|
||||||
.to_string();
|
|
||||||
let first_char = chars_ignoring_modifiers.chars().next().map(|ch| ch as u16);
|
let first_char = chars_ignoring_modifiers.chars().next().map(|ch| ch as u16);
|
||||||
let modifiers = native_event.modifierFlags();
|
let modifiers = native_event.modifierFlags();
|
||||||
|
|
||||||
|
@ -351,9 +350,6 @@ fn chars_for_modified_key(code: CGKeyCode, cmd: bool, shift: bool) -> String {
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
let event: id = msg_send![class!(NSEvent), eventWithCGEvent: &*event];
|
let event: id = msg_send![class!(NSEvent), eventWithCGEvent: &*event];
|
||||||
CStr::from_ptr(event.characters().UTF8String())
|
event.characters().to_str().to_string()
|
||||||
.to_str()
|
|
||||||
.unwrap()
|
|
||||||
.to_string()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
use super::{ns_string, renderer, MacDisplay, NSRange};
|
use super::{ns_string, renderer, MacDisplay, NSRange, NSStringExt};
|
||||||
use crate::{
|
use crate::{
|
||||||
platform::PlatformInputHandler, point, px, size, AnyWindowHandle, Bounds, DevicePixels,
|
platform::PlatformInputHandler, point, px, size, AnyWindowHandle, Bounds, DevicePixels,
|
||||||
DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke,
|
DisplayLink, ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke,
|
||||||
|
@ -39,7 +39,6 @@ use std::{
|
||||||
ffi::{c_void, CStr},
|
ffi::{c_void, CStr},
|
||||||
mem,
|
mem,
|
||||||
ops::Range,
|
ops::Range,
|
||||||
os::raw::c_char,
|
|
||||||
path::PathBuf,
|
path::PathBuf,
|
||||||
ptr::{self, NonNull},
|
ptr::{self, NonNull},
|
||||||
rc::Rc,
|
rc::Rc,
|
||||||
|
@ -1711,9 +1710,8 @@ extern "C" fn insert_text(this: &Object, _: Sel, text: id, replacement_range: NS
|
||||||
} else {
|
} else {
|
||||||
text
|
text
|
||||||
};
|
};
|
||||||
let text = CStr::from_ptr(text.UTF8String() as *mut c_char)
|
|
||||||
.to_str()
|
let text = text.to_str();
|
||||||
.unwrap();
|
|
||||||
let replacement_range = replacement_range.to_range();
|
let replacement_range = replacement_range.to_range();
|
||||||
send_to_input_handler(
|
send_to_input_handler(
|
||||||
this,
|
this,
|
||||||
|
@ -1739,9 +1737,7 @@ extern "C" fn set_marked_text(
|
||||||
};
|
};
|
||||||
let selected_range = selected_range.to_range();
|
let selected_range = selected_range.to_range();
|
||||||
let replacement_range = replacement_range.to_range();
|
let replacement_range = replacement_range.to_range();
|
||||||
let text = CStr::from_ptr(text.UTF8String() as *mut c_char)
|
let text = text.to_str();
|
||||||
.to_str()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
send_to_input_handler(
|
send_to_input_handler(
|
||||||
this,
|
this,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue