{"record":{"id":"6e9437f6ddd14c51","repo":"linebender/druid","slug":"acquire-input-lock-was-called-on-a-winhandler-that","errorCode":null,"errorMessage":"acquire_input_lock was called on a WinHandler that did not expect text input.","messagePattern":"acquire_input_lock was called on a WinHandler that did not expect text input\\.","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"druid-shell/src/window.rs","lineNumber":662,"sourceCode":"    /// Take a lock for the text document specified by `token`.\n    ///\n    /// All calls to this method must be balanced with a call to\n    /// [`release_input_lock`].\n    ///\n    /// If `mutable` is true, the lock should be a write lock, and allow calling\n    /// mutating methods on InputHandler.  This method is called from the top\n    /// level of the event loop and expects to acquire a lock successfully.\n    ///\n    /// For more information, see [the text input documentation](crate::text).\n    ///\n    /// [`release_input_lock`]: WinHandler::release_input_lock\n    #[allow(unused_variables)]\n    fn acquire_input_lock(\n        &mut self,\n        token: TextFieldToken,\n        mutable: bool,\n    ) -> Box<dyn InputHandler> {\n        panic!(\"acquire_input_lock was called on a WinHandler that did not expect text input.\")\n    }\n\n    /// Release a lock previously acquired by [`acquire_input_lock`].\n    ///\n    /// [`acquire_input_lock`]: WinHandler::acquire_input_lock\n    #[allow(unused_variables)]\n    fn release_input_lock(&mut self, token: TextFieldToken) {\n        panic!(\"release_input_lock was called on a WinHandler that did not expect text input.\")\n    }\n\n    /// Called on a mouse wheel event.\n    ///\n    /// The polarity is the amount to be added to the scroll position,\n    /// in other words the opposite of the direction the content should\n    /// move on scrolling. This polarity is consistent with the\n    /// deltaX and deltaY values in a web [WheelEvent].\n    ///\n    /// [WheelEvent]: https://w3c.github.io/uievents/#event-type-wheel","sourceCodeStart":644,"sourceCodeEnd":680,"githubUrl":"https://github.com/linebender/druid/blob/0f8b1195e4e073f9597f2865299c3d18f8e4005f/druid-shell/src/window.rs#L644-L680","documentation":"This panic is the default (no-op) implementation of `WinHandler::acquire_input_lock` in druid-shell's window.rs. The shell calls it when a platform IME/text-input path tries to lock a text field, but the application's WinHandler never registered text fields, so it has no InputHandler to return. It is a contract violation: the handler received a text-input request it did not opt into.","triggerScenarios":"The platform backend (e.g. IME focus handling) calls `acquire_input_lock(token, mutable)` on a WinHandler whose default trait method was not overridden and which never returned a matching TextFieldToken from `text_widgets`/focus tracking.","commonSituations":"Custom WinHandler implementations that use the default trait impls; IME or accessibility events arriving for a text field that was removed or never registered; upgrading druid-shell where the backend now routes input through the lock API for handlers written against older versions.","solutions":["Override `acquire_input_lock` in your WinHandler to return the InputHandler for the given TextFieldToken","Ensure the token passed corresponds to a text field your handler actually registered; verify what token the platform is asking for","If your app has no text input at all, check why the backend is requesting a lock (stray focus/IME event) and guard the widget registration"],"exampleFix":"// before\nimpl WinHandler for MyAppHandler {} // uses panicking default\n// after\nimpl WinHandler for MyAppHandler {\n    fn acquire_input_lock(\n        &mut self,\n        token: TextFieldToken,\n        mutable: bool,\n    ) -> Box<dyn InputHandler> {\n        match self.text_field_for(token) {\n            Some(field) => Box::new(field.lock_input(mutable)),\n            None => Box::new(NullInputHandler),\n        }\n    }\n}","handlingStrategy":"type-guard","validationCode":"// Before enabling text input, verify the handler implements the input-lock API:\nfn supports_text_input(handler: &dyn WinHandler, token: TextFieldToken) -> bool {\n    handler.text_widgets().contains(&token)\n}\n","typeGuard":"fn handler_overrides_input_lock(handler: &dyn WinHandler) -> bool {\n    // default impl panics; only route text events to handlers that registered fields\n    !handler.text_widgets().is_empty()\n}\n","tryCatchPattern":"// Rust panics are not catchable in normal code; if you must:\nlet result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {\n    handler.acquire_input_lock(token, true)\n}));\nif result.is_err() { tracing::error!(\"handler does not support text input\"); }\n","preventionTips":["Override acquire_input_lock/release_input_lock whenever your WinHandler registers text fields","Keep text field registration and lock overrides in the same impl block","Test with IME input enabled to exercise the lock path","After druid-shell upgrades, audit WinHandler impls against the trait's new methods"],"tags":["rust","druid-shell","text-input","winhandler"],"backgroundTag":"method-not-implemented","analyzedSha":"0f8b1195e4e073f9597f2865299c3d18f8e4005f","analyzedAt":"2026-09-10T14:27:34.582Z","contentChangedAt":"2026-09-10T14:27:34.582Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}