Skip to content

Commit 70056b2

Browse files
committed
Gtk*Backend: Disable default escape-to-close alert shortcut to fix crash
Will conditionally re-enable in scenarios where we know which button is the benign action, but for now this is the best we can do, and just makes sense anyway.
1 parent cacdd47 commit 70056b2

File tree

4 files changed

+45
-2
lines changed

4 files changed

+45
-2
lines changed

Sources/Gtk/Utility/CSS/CSSProvider.swift

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ public class CSSProvider {
55
var pointer: UnsafeMutablePointer<GtkCssProvider>
66
var display: OpaquePointer
77

8-
init(
8+
public init(
99
forDisplay display: OpaquePointer = gdk_display_get_default(),
1010
priority: UInt32 = UInt32(GTK_STYLE_PROVIDER_PRIORITY_APPLICATION)
1111
) {
@@ -24,6 +24,7 @@ public class CSSProvider {
2424
///
2525
/// Deprecated since: 4.12
2626
public func loadCss(from data: String) {
27+
// TODO: Connect to parsing-error signal to log parsing errors.
2728
gtk_css_provider_load_from_data(pointer, data, gssize(data.count))
2829
}
2930
}

Sources/Gtk3/Utility/CSS/CSSProvider.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,5 +34,9 @@ public class CSSProvider {
3434
public func loadCss(from data: String) {
3535
var error: UnsafeMutablePointer<GError>? = nil
3636
gtk_css_provider_load_from_data(pointer, data, gssize(data.count), &error)
37+
if let error {
38+
let message = String(cString: error.pointee.message)
39+
print("warning: Failed to load CSS: \(message)")
40+
}
3741
}
3842
}

Sources/Gtk3Backend/Gtk3Backend.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,14 @@ public final class Gtk3Backend: AppBackend {
7070
padding-top: 11px;
7171
margin-bottom: -10px;
7272
}
73+
74+
@binding-set DisableEscape {
75+
unbind "Escape";
76+
}
77+
78+
messagedialog {
79+
-gtk-key-bindings: DisableEscape;
80+
}
7381
"""
7482
)
7583
gtk_style_context_add_provider_for_screen(
@@ -822,10 +830,12 @@ public final class Gtk3Backend: AppBackend {
822830

823831
public func createAlert() -> Alert {
824832
let dialog = Gtk3.MessageDialog()
833+
825834
// The Ubuntu Gtk3 theme seems to only set the bottom corner radii.
826835
dialog.css.set(properties: [
827836
.cornerRadius(13)
828837
])
838+
829839
return dialog
830840
}
831841

@@ -847,6 +857,14 @@ public final class Gtk3Backend: AppBackend {
847857
responseHandler handleResponse: @escaping (Int) -> Void
848858
) {
849859
alert.response = { _, responseId in
860+
guard responseId != Int(UInt32(bitPattern: -4)) else {
861+
// Ignore escape key for now. Once we support detecting
862+
// the primary and secondary actions of alerts we can wire
863+
// this up to whichever action is the default cancellation
864+
// action.
865+
return
866+
}
867+
850868
alert.destroy()
851869
handleResponse(responseId)
852870
}

Sources/GtkBackend/GtkBackend.swift

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -830,7 +830,19 @@ public final class GtkBackend: AppBackend {
830830
}
831831

832832
public func createAlert() -> Alert {
833-
Gtk.MessageDialog()
833+
let dialog = Gtk.MessageDialog()
834+
835+
// Register a custom shortcut controller to disable the default Escape-to-close
836+
// action. In future we'll probably want to conditionally re-enable this
837+
// shortcut in scenarios where we know which action button is the cancel action.
838+
let controller = gtk_shortcut_controller_new()
839+
let trigger = gtk_shortcut_trigger_parse_string("Escape")
840+
let action = gtk_callback_action_new({ _, _, _ in return 1 }, nil, { _ in })
841+
let shortcut = gtk_shortcut_new(trigger, action)
842+
gtk_shortcut_controller_add_shortcut(controller, shortcut)
843+
gtk_widget_add_controller(dialog.widgetPointer, controller)
844+
845+
return dialog
834846
}
835847

836848
public func updateAlert(
@@ -851,6 +863,14 @@ public final class GtkBackend: AppBackend {
851863
responseHandler handleResponse: @escaping (Int) -> Void
852864
) {
853865
alert.response = { _, responseId in
866+
guard responseId != Int(UInt32(bitPattern: -4)) else {
867+
// Ignore escape key for now. Once we support detecting
868+
// the primary and secondary actions of alerts we can wire
869+
// this up to whichever action is the default cancellation
870+
// action.
871+
return
872+
}
873+
854874
alert.destroy()
855875
handleResponse(responseId)
856876
}

0 commit comments

Comments
 (0)