3416 lines · 127.4 KB · Rust
RawDownload
use crate::{    BoolExt, MacDisplay, NSRange, NSStringExt, TISCopyCurrentKeyboardInputSource,    TISGetInputSourceProperty, WindowFrameSource, events::platform_input_from_native,    kTISPropertyInputSourceIsASCIICapable, kTISPropertyInputSourceType, kTISTypeKeyboardInputMode,    ns_string, renderer,};#[cfg(any(test, feature = "test-support"))]use anyhow::Result;use block::ConcreteBlock;use cocoa::{    appkit::{        NSApplication, NSBackingStoreBuffered, NSColor, NSEvent, NSEventModifierFlags, NSEventType,        NSFilenamesPboardType, NSPasteboard, NSRequestUserAttentionType, NSScreen, NSView,        NSViewHeightSizable, NSViewWidthSizable, NSVisualEffectMaterial, NSVisualEffectState,        NSVisualEffectView, NSWindow, NSWindowCollectionBehavior, NSWindowOcclusionState,        NSWindowOrderingMode, NSWindowStyleMask, NSWindowTitleVisibility,    },    base::{id, nil},    foundation::{        NSArray, NSAutoreleasePool, NSDictionary, NSFastEnumeration, NSInteger, NSNotFound,        NSOperatingSystemVersion, NSPoint, NSProcessInfo, NSRect, NSSize, NSString, NSUInteger,        NSUserDefaults,    },};use dispatch2::DispatchQueue;use gpui::{    AnyWindowHandle, BackgroundExecutor, Bounds, Capslock, CursorStyle, ExternalDragPayload,    ExternalPaths, FileDropEvent, ForegroundExecutor, KeyDownEvent, Keystroke, Modifiers,    ModifiersChangedEvent, MouseButton, MouseDownEvent, MouseMoveEvent, MouseUpEvent, Pixels,    PlatformAtlas, PlatformDisplay, PlatformInput, PlatformInputHandler, PlatformWindow, Point,    PromptButton, PromptLevel, RequestFrameOptions, SharedString, Size, SystemWindowTab,    WindowAppearance, WindowBackgroundAppearance, WindowBounds, WindowControlArea, WindowKind,    WindowParams, point, px, size,};#[cfg(any(test, feature = "test-support"))]use image::RgbaImage; use core_foundation::base::{CFRelease, CFTypeRef};use core_foundation_sys::base::CFEqual;use core_foundation_sys::number::{CFBooleanGetValue, CFBooleanRef};use core_graphics::display::{CGDirectDisplayID, CGRect};use ctor::ctor;use futures::channel::oneshot;use gpui_util::ResultExt;use objc::{    class,    declare::ClassDecl,    msg_send,    runtime::{BOOL, Class, NO, Object, Protocol, Sel, YES},    sel, sel_impl,};use objc2::{rc::Retained, runtime::AnyObject as Objc2Object};use objc2_app_kit::{    NSBeep, NSButton as Objc2NSButton, NSView as Objc2NSView, NSWindow as Objc2NSWindow,    NSWindowButton as Objc2NSWindowButton,};use objc2_foundation::{NSPoint as Objc2NSPoint, NSRect as Objc2NSRect};use parking_lot::Mutex;use raw_window_handle as rwh;use smallvec::SmallVec;use std::{    cell::Cell,    ffi::{CStr, CString, c_void},    mem,    ops::Range,    os::unix::ffi::OsStrExt,    path::PathBuf,    ptr::{self, NonNull},    rc::Rc,    sync::{        Arc, Weak,        atomic::{AtomicBool, Ordering},    },    time::Duration,}; const WINDOW_STATE_IVAR: &str = "windowState"; static mut WINDOW_CLASS: *const Class = ptr::null();static mut PANEL_CLASS: *const Class = ptr::null();static mut VIEW_CLASS: *const Class = ptr::null();static mut BLURRED_VIEW_CLASS: *const Class = ptr::null(); #[allow(non_upper_case_globals)]const NSWindowStyleMaskNonactivatingPanel: NSWindowStyleMask =    NSWindowStyleMask::from_bits_retain(1 << 7);// WindowLevel const value ref: https://docs.rs/core-graphics2/0.4.1/src/core_graphics2/window_level.rs.html#[allow(non_upper_case_globals)]const NSNormalWindowLevel: NSInteger = 0;#[allow(non_upper_case_globals)]const NSFloatingWindowLevel: NSInteger = 3;#[allow(non_upper_case_globals)]const NSPopUpWindowLevel: NSInteger = 101;#[allow(non_upper_case_globals)]const NSTrackingMouseEnteredAndExited: NSUInteger = 0x01;#[allow(non_upper_case_globals)]const NSTrackingMouseMoved: NSUInteger = 0x02;#[allow(non_upper_case_globals)]const NSTrackingActiveAlways: NSUInteger = 0x80;#[allow(non_upper_case_globals)]const NSTrackingInVisibleRect: NSUInteger = 0x200;#[allow(non_upper_case_globals)]const NSWindowAnimationBehaviorUtilityWindow: NSInteger = 4;#[allow(non_upper_case_globals)]const NSViewLayerContentsRedrawDuringViewResize: NSInteger = 2;// https://developer.apple.com/documentation/appkit/nsdragoperationtype NSDragOperation = NSUInteger;#[allow(non_upper_case_globals)]const NSDragOperationNone: NSDragOperation = 0;#[allow(non_upper_case_globals)]const NSDragOperationCopy: NSDragOperation = 1;#[allow(non_upper_case_globals)]const NSDragOperationMove: NSDragOperation = 16;const NSDRAGGING_CONTEXT_OUTSIDE_APPLICATION: NSInteger = 0;const NSDRAGGING_CONTEXT_WITHIN_APPLICATION: NSInteger = 1;#[derive(PartialEq)]pub enum UserTabbingPreference {    Never,    Always,    InFullScreen,} #[link(name = "AppKit", kind = "framework")]unsafe extern "C" {    // AppKit constant naming the icon component of an NSDraggingImageComponent.    #[allow(non_upper_case_globals)]    static NSDraggingImageComponentIconKey: id;}#[ctor(unsafe)]unsafe fn build_classes() {    unsafe {        WINDOW_CLASS = build_window_class("GPUIWindow", class!(NSWindow));        PANEL_CLASS = build_window_class("GPUIPanel", class!(NSPanel));        VIEW_CLASS = {            let mut decl = ClassDecl::new("GPUIView", class!(NSView)).unwrap();            decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);            decl.add_method(sel!(dealloc), dealloc_view as extern "C" fn(&Object, Sel));             decl.add_method(                sel!(performKeyEquivalent:),                handle_key_equivalent as extern "C" fn(&Object, Sel, id) -> BOOL,            );            decl.add_method(                sel!(keyDown:),                handle_key_down as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(keyUp:),                handle_key_up as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(mouseDown:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(mouseUp:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(rightMouseDown:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(rightMouseUp:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(otherMouseDown:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(otherMouseUp:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(mouseMoved:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(resetCursorRects),                reset_cursor_rects as extern "C" fn(&Object, Sel),            );            decl.add_method(                sel!(pressureChangeWithEvent:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(mouseExited:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(magnifyWithEvent:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(mouseDragged:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(rightMouseDragged:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(otherMouseDragged:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(scrollWheel:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(swipeWithEvent:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );            decl.add_method(                sel!(flagsChanged:),                handle_view_event as extern "C" fn(&Object, Sel, id),            );             decl.add_method(                sel!(makeBackingLayer),                make_backing_layer as extern "C" fn(&Object, Sel) -> id,            );             decl.add_protocol(Protocol::get("CALayerDelegate").unwrap());            decl.add_method(                sel!(viewDidChangeBackingProperties),                view_did_change_backing_properties as extern "C" fn(&Object, Sel),            );            decl.add_method(                sel!(setFrameSize:),                set_frame_size as extern "C" fn(&Object, Sel, NSSize),            );            decl.add_method(                sel!(displayLayer:),                display_layer as extern "C" fn(&Object, Sel, id),            );             decl.add_protocol(Protocol::get("NSTextInputClient").unwrap());            decl.add_method(                sel!(validAttributesForMarkedText),                valid_attributes_for_marked_text as extern "C" fn(&Object, Sel) -> id,            );            decl.add_method(                sel!(hasMarkedText),                has_marked_text as extern "C" fn(&Object, Sel) -> BOOL,            );            decl.add_method(                sel!(markedRange),                marked_range as extern "C" fn(&Object, Sel) -> NSRange,            );            decl.add_method(                sel!(selectedRange),                selected_range as extern "C" fn(&Object, Sel) -> NSRange,            );            decl.add_method(                sel!(firstRectForCharacterRange:actualRange:),                first_rect_for_character_range                    as extern "C" fn(&Object, Sel, NSRange, id) -> NSRect,            );            decl.add_method(                sel!(insertText:replacementRange:),                insert_text as extern "C" fn(&Object, Sel, id, NSRange),            );            decl.add_method(                sel!(setMarkedText:selectedRange:replacementRange:),                set_marked_text as extern "C" fn(&Object, Sel, id, NSRange, NSRange),            );            decl.add_method(sel!(unmarkText), unmark_text as extern "C" fn(&Object, Sel));            decl.add_method(                sel!(attributedSubstringForProposedRange:actualRange:),                attributed_substring_for_proposed_range                    as extern "C" fn(&Object, Sel, NSRange, *mut c_void) -> id,            );            decl.add_method(                sel!(viewDidChangeEffectiveAppearance),                view_did_change_effective_appearance as extern "C" fn(&Object, Sel),            );             // Suppress beep on keystrokes with modifier keys.            decl.add_method(                sel!(doCommandBySelector:),                do_command_by_selector as extern "C" fn(&Object, Sel, Sel),            );             decl.add_method(                sel!(acceptsFirstMouse:),                accepts_first_mouse as extern "C" fn(&Object, Sel, id) -> BOOL,            );             decl.add_method(                sel!(_opaqueRectForWindowMoveWhenInTitlebar),                opaque_rect_for_window_move_when_in_titlebar                    as extern "C" fn(&Object, Sel) -> NSRect,            );             decl.add_method(                sel!(characterIndexForPoint:),                character_index_for_point as extern "C" fn(&Object, Sel, NSPoint) -> u64,            );            decl.register()        };        BLURRED_VIEW_CLASS = {            let mut decl = ClassDecl::new("BlurredView", class!(NSVisualEffectView)).unwrap();            decl.add_method(                sel!(initWithFrame:),                blurred_view_init_with_frame as extern "C" fn(&Object, Sel, NSRect) -> id,            );            decl.add_method(                sel!(updateLayer),                blurred_view_update_layer as extern "C" fn(&Object, Sel),            );            decl.register()        };    }} pub(crate) fn convert_mouse_position(position: NSPoint, window_height: Pixels) -> Point<Pixels> {    point(        px(position.x as f32),        // macOS screen coordinates are relative to bottom left        window_height - px(position.y as f32),    )} /// Stores the cursor style on the active GPUI window and invalidates its cursor rects.////// # Safety////// This function is not thread safe. Callers must ensure this is called on the AppKit main/// thread because it reads the active AppKit window and updates GPUI window state associated/// with Objective-C objects.pub(crate) unsafe fn set_active_window_cursor_style(style: CursorStyle) {    // SAFETY: The caller guarantees AppKit main-thread access. `is_gpui_window` ensures the    // window has our WINDOW_STATE_IVAR before reading it.    unsafe {        let app = NSApplication::sharedApplication(nil);        let key_window: id = msg_send![app, keyWindow];        let main_window: id = msg_send![app, mainWindow];        let active_window = if !key_window.is_null() && is_gpui_window(key_window) {            Some(key_window)        } else if !main_window.is_null() && is_gpui_window(main_window) {            Some(main_window)        } else {            None        };         let Some(active_window) = active_window else {            return;        };         let window_state = get_window_state(&*active_window);        let mut window_state = window_state.lock();        if window_state.cursor_style != style {            window_state.cursor_style = style;            let _: () = msg_send![                window_state.native_window,                invalidateCursorRectsForView: window_state.native_view.as_ptr()            ];        }    }} unsafe fn build_window_class(name: &'static str, superclass: &Class) -> *const Class {    unsafe {        let mut decl = ClassDecl::new(name, superclass).unwrap();        decl.add_ivar::<*mut c_void>(WINDOW_STATE_IVAR);        decl.add_method(sel!(dealloc), dealloc_window as extern "C" fn(&Object, Sel));         decl.add_method(            sel!(canBecomeMainWindow),            yes as extern "C" fn(&Object, Sel) -> BOOL,        );        decl.add_method(            sel!(canBecomeKeyWindow),            yes as extern "C" fn(&Object, Sel) -> BOOL,        );        decl.add_method(            sel!(windowDidResize:),            window_did_resize as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowDidChangeOcclusionState:),            window_did_change_occlusion_state as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowWillEnterFullScreen:),            window_will_enter_fullscreen as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowWillExitFullScreen:),            window_will_exit_fullscreen as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowDidExitFullScreen:),            window_did_exit_fullscreen as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowDidMove:),            window_did_move as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowDidChangeScreen:),            window_did_change_screen as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowDidBecomeKey:),            window_did_change_key_status as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowDidResignKey:),            window_did_change_key_status as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(windowShouldClose:),            window_should_close as extern "C" fn(&Object, Sel, id) -> BOOL,        );         decl.add_method(sel!(close), close_window as extern "C" fn(&Object, Sel));         decl.add_method(            sel!(draggingEntered:),            dragging_entered as extern "C" fn(&Object, Sel, id) -> NSDragOperation,        );        decl.add_method(            sel!(draggingUpdated:),            dragging_updated as extern "C" fn(&Object, Sel, id) -> NSDragOperation,        );        decl.add_method(            sel!(draggingExited:),            dragging_exited as extern "C" fn(&Object, Sel, id),        );        decl.add_method(            sel!(performDragOperation:),            perform_drag_operation as extern "C" fn(&Object, Sel, id) -> BOOL,        );        decl.add_method(            sel!(concludeDragOperation:),            conclude_drag_operation as extern "C" fn(&Object, Sel, id),        );         decl.add_protocol(Protocol::get("NSDraggingSource").unwrap());        decl.add_method(            sel!(draggingSession:sourceOperationMaskForDraggingContext:),            dragging_session_source_operation_mask                as extern "C" fn(&Object, Sel, id, NSInteger) -> NSDragOperation,        );        decl.add_method(            sel!(draggingSession:endedAtPoint:operation:),            dragging_session_ended as extern "C" fn(&Object, Sel, id, NSPoint, NSDragOperation),        );         decl.add_method(            sel!(addTitlebarAccessoryViewController:),            add_titlebar_accessory_view_controller as extern "C" fn(&Object, Sel, id),        );         decl.add_method(            sel!(moveTabToNewWindow:),            move_tab_to_new_window as extern "C" fn(&Object, Sel, id),        );         decl.add_method(            sel!(mergeAllWindows:),            merge_all_windows as extern "C" fn(&Object, Sel, id),        );         decl.add_method(            sel!(selectNextTab:),            select_next_tab as extern "C" fn(&Object, Sel, id),        );         decl.add_method(            sel!(selectPreviousTab:),            select_previous_tab as extern "C" fn(&Object, Sel, id),        );         decl.add_method(            sel!(toggleTabBar:),            toggle_tab_bar as extern "C" fn(&Object, Sel, id),        );         decl.register()    }} struct TrafficLightFrames {    titlebar: Objc2NSRect,    close: Objc2NSRect,    minimize: Objc2NSRect,    zoom: Objc2NSRect,} struct TrafficLightButtons {    close: Retained<Objc2NSButton>,    minimize: Retained<Objc2NSButton>,    zoom: Retained<Objc2NSButton>,} struct MacWindowState {

Lines 1–500 of 3416.