         return connectSignal(name: WidgetSignalName.draw.rawValue, flags: f, handler: handler)
     }
 
+    /// Connect a `(WidgetRef, Gdk.EventKeyRef) -> Void` closure or function to a button event signal for the receiver.
+    /// Before calling this, you need to call `add(events:)`, e.g.
+    /// widget.add(events: CInt(GDK_KEY_PRESS_MASK.rawValue)
+    ///
+    /// - Parameters:
+    ///   - event: widget signal name (defaults to `.keyPressEvent`)
+    ///   - f: connection flags (defaults to `0`)
+    ///   - handler: signal handler
+    /// - Returns: the corresponding return value of `g_signal_connect()`
+    @discardableResult
+    public func onKey(event: WidgetSignalName = .keyPressEvent, flags f: ConnectFlags = ConnectFlags(0), handler: @escaping KeySignalHandler) -> CUnsignedLong {
+        return connectKey(signal: event.rawValue, flags: f, handler: handler)
+    }
+
+    /// Connect a `(WidgetRef, Gdk.EventKeyRef) -> Void` closure or function to the `.keyPressEvent` signal for the receiver.
+    /// This method adds the `GDK_KEY_PRESS_MASK` to the widget prior to connecting the closure.
+    ///
+    /// - Parameters:
+    ///   - f: connection flags (defaults to `0`)
+    ///   - handler: signal handler
+    /// - Returns: the corresponding return value of `g_signal_connect()`
+    @discardableResult
+    public func onKeyPress(flags f: ConnectFlags = ConnectFlags(0), handler h: @escaping KeySignalHandler) -> CUnsignedLong {
+        add(events: CInt(GDK_KEY_PRESS_MASK.rawValue))
+        return onKey(event: .keyPressEvent, flags: f, handler: h)
+    }
+
+    /// Connect a `(WidgetRef, Gdk.EventKeyRef) -> Void` closure or function to the `.keyReleaseEvent` signal for the receiver.
+    /// This method adds the `GDK_KEY_RELEASE_MASK` to the widget prior to connecting the closure.
+    ///
+    /// - Parameters:
+    ///   - f: connection flags (defaults to `0`)
+    ///   - handler: signal handler
+    /// - Returns: the corresponding return value of `g_signal_connect()`
+    @discardableResult
+    public func onKeyRelease(flags f: ConnectFlags = ConnectFlags(0), handler h: @escaping KeySignalHandler) -> CUnsignedLong {
+        add(events: CInt(GDK_KEY_RELEASE_MASK.rawValue))
+        return onKey(event: .keyReleaseEvent, flags: f, handler: h)
+    }
+
     /// Connect a `(WidgetRef, Gdk.EventButtonRef) -> Void` closure or function to a button event signal for the receiver.
     /// Before calling this, you need to call `add(events:)`, e.g.
     /// widget.add(events: CInt(GDK_BUTTON_PRESS_MASK.rawValue)

    }

    /// Connection helper function
    private func _connect(signal name: UnsafePointer<gchar>, flags: ConnectFlags, data: ButtonSignalHandlerClosureHolder, handler: @convention(c) @escaping (gpointer, gpointer, gpointer) -> Void) -> CUnsignedLong {
        let opaqueHolder = Unmanaged.passRetained(data).toOpaque()
        let callback = unsafeBitCast(handler, to: Callback.self)


/// Internal type for Drawing SignalHandler closure holder
typealias WidgetSignalHandlerClosureHolder = DualClosureHolder<WidgetRef,Cairo.ContextRef, Bool>

/// Internal type for key event SignalHandler closure holder
typealias KeySignalHandlerClosureHolder = DualClosureHolder<WidgetRef, Gdk.EventKeyRef, Void>

/// Internal type for button event SignalHandler closure holder
typealias ButtonSignalHandlerClosureHolder = DualClosureHolder<WidgetRef, Gdk.EventButtonRef, Void>
