@@ -35,6 +35,7 @@ struct _WindowManagerPlugin {
3535 bool _is_resizing = false ;
3636 gchar* title_bar_style_ = strdup(" normal" );
3737 GdkEventButton _event_button = GdkEventButton{};
38+ GdkDevice* grab_pointer;
3839};
3940
4041G_DEFINE_TYPE (WindowManagerPlugin, window_manager_plugin, g_object_get_type())
@@ -443,11 +444,11 @@ static FlMethodResponse* set_skip_taskbar(WindowManagerPlugin* self,
443444 return FL_METHOD_RESPONSE (fl_method_success_response_new (result));
444445}
445446
446- static FlMethodResponse* set_icon (WindowManagerPlugin* self,
447- FlValue* args) {
447+ static FlMethodResponse* set_icon (WindowManagerPlugin* self, FlValue* args) {
448448 const gchar* file_name =
449449 fl_value_get_string (fl_value_lookup_string (args, " iconPath" ));
450- const gboolean gtk_result = gtk_window_set_icon_from_file (get_window (self), file_name, NULL );
450+ const gboolean gtk_result =
451+ gtk_window_set_icon_from_file (get_window (self), file_name, NULL );
451452 g_autoptr (FlValue) result = fl_value_new_bool (gtk_result);
452453 return FL_METHOD_RESPONSE (fl_method_success_response_new (result));
453454}
@@ -572,6 +573,89 @@ static FlMethodResponse* start_resizing(WindowManagerPlugin* self,
572573 return FL_METHOD_RESPONSE (fl_method_success_response_new (result));
573574}
574575
576+ static const gchar* gdk_grab_status_code (GdkGrabStatus status) {
577+ switch (status) {
578+ case GDK_GRAB_SUCCESS:
579+ return " GDK_GRAB_SUCCESS" ;
580+ case GDK_GRAB_ALREADY_GRABBED:
581+ return " GDK_GRAB_ALREADY_GRABBED" ;
582+ case GDK_GRAB_INVALID_TIME:
583+ return " GDK_GRAB_INVALID_TIME" ;
584+ case GDK_GRAB_NOT_VIEWABLE:
585+ return " GDK_GRAB_NOT_VIEWABLE" ;
586+ case GDK_GRAB_FROZEN:
587+ return " GDK_GRAB_FROZEN" ;
588+ case GDK_GRAB_FAILED:
589+ return " GDK_GRAB_FAILED" ;
590+ default :
591+ return " GDK_GRAB_???" ;
592+ }
593+ }
594+
595+ static const gchar* gdk_grab_status_message (GdkGrabStatus status) {
596+ switch (status) {
597+ case GDK_GRAB_SUCCESS:
598+ return " The resource was successfully grabbed." ;
599+ case GDK_GRAB_ALREADY_GRABBED:
600+ return " The resource is actively grabbed by another client." ;
601+ case GDK_GRAB_INVALID_TIME:
602+ return " The resource was grabbed more recently than the specified time." ;
603+ case GDK_GRAB_NOT_VIEWABLE:
604+ return " The grab window or the confine_to window are not viewable." ;
605+ case GDK_GRAB_FROZEN:
606+ return " The resource is frozen by an active grab of another client." ;
607+ case GDK_GRAB_FAILED:
608+ return " The grab failed for some other reason." ;
609+ default :
610+ return " The grab status is unknown." ;
611+ }
612+ }
613+
614+ static GdkGrabStatus gdk_grab_keyboard (WindowManagerPlugin* self) {
615+ g_return_val_if_fail (self->grab_pointer == nullptr , GDK_GRAB_FAILED);
616+
617+ auto window = get_window (self);
618+ auto screen = gtk_window_get_screen (window);
619+ auto display = gdk_screen_get_display (screen);
620+ auto seat = gdk_display_get_default_seat (display);
621+ auto gdk_window = get_gdk_window (self);
622+
623+ GdkGrabStatus status = gdk_seat_grab (
624+ seat, gdk_window, GDK_SEAT_CAPABILITY_KEYBOARD, false /* owner_events */ ,
625+ nullptr /* cursor */ , nullptr /* event */ , nullptr /* prepare_func */ ,
626+ nullptr /* prepare_func_data */ );
627+
628+ self->grab_pointer = gdk_seat_get_keyboard (seat);
629+ if (!self->grab_pointer ) {
630+ self->grab_pointer = gdk_seat_get_pointer (seat);
631+ }
632+
633+ return status;
634+ }
635+
636+ static FlMethodResponse* grab_keyboard (WindowManagerPlugin* self) {
637+ GdkGrabStatus status = gdk_grab_keyboard (self);
638+
639+ if (status != GDK_GRAB_SUCCESS) {
640+ return FL_METHOD_RESPONSE (
641+ fl_method_error_response_new (gdk_grab_status_code (status),
642+ gdk_grab_status_message (status), nullptr ));
643+ }
644+
645+ g_autoptr (FlValue) result = fl_value_new_bool (true );
646+ return FL_METHOD_RESPONSE (fl_method_success_response_new (result));
647+ }
648+
649+ static FlMethodResponse* ungrab_keyboard (WindowManagerPlugin* self) {
650+ if (self->grab_pointer != nullptr ) {
651+ gdk_seat_ungrab (gdk_device_get_seat (self->grab_pointer ));
652+ self->grab_pointer = nullptr ;
653+ }
654+
655+ g_autoptr (FlValue) result = fl_value_new_bool (true );
656+ return FL_METHOD_RESPONSE (fl_method_success_response_new (result));
657+ }
658+
575659// Called when a method call is received from Flutter.
576660static void window_manager_plugin_handle_method_call (
577661 WindowManagerPlugin* self,
@@ -677,6 +761,10 @@ static void window_manager_plugin_handle_method_call(
677761 response = start_dragging (self);
678762 } else if (strcmp (method, " startResizing" ) == 0 ) {
679763 response = start_resizing (self, args);
764+ } else if (strcmp (method, " grabKeyboard" ) == 0 ) {
765+ response = grab_keyboard (self);
766+ } else if (strcmp (method, " ungrabKeyboard" ) == 0 ) {
767+ response = ungrab_keyboard (self);
680768 } else {
681769 response = FL_METHOD_RESPONSE (fl_method_not_implemented_response_new ());
682770 }
0 commit comments