Gtk3: fixed gtk3 forms behaviour.

This commit is contained in:
zeljan1 2025-01-21 13:34:56 +01:00
parent df2710224f
commit 86bba40f39

View File

@ -214,9 +214,35 @@ begin
TGtk3Widget(AWinControl.Handle).SetBounds(ALeft,ATop,AWidth,AHeight); TGtk3Widget(AWinControl.Handle).SetBounds(ALeft,ATop,AWidth,AHeight);
end; end;
{$IFDEF GTK3DEBUGCORE}
procedure ReleaseInputGrab;
var
Display: PGdkDisplay;
Seat: PGdkSeat;
begin
// Get the default display
Display := gdk_display_get_default();
if not Assigned(Display) then
begin
WriteLn('Error: No default display available.');
Exit;
end;
// Get the default seat
Seat := gdk_display_get_default_seat(Display);
if not Assigned(Seat) then
begin
WriteLn('Error: No default seat available.');
Exit;
end;
Gtk3WidgetSet.SetCapture(0);
gdk_seat_ungrab(Seat);
end;
{$ENDIF}
class procedure TGtk3WSCustomForm.ShowHide(const AWinControl: TWinControl); class procedure TGtk3WSCustomForm.ShowHide(const AWinControl: TWinControl);
var var
AMask: TGdkEventMask; AMask:TGdkEventMask;
AForm, OtherForm: TCustomForm; AForm, OtherForm: TCustomForm;
AWindow: PGtkWindow; AWindow: PGtkWindow;
i: Integer; i: Integer;
@ -241,54 +267,74 @@ begin
else else
AWindow := nil; AWindow := nil;
ShouldBeVisible:=AForm.HandleObjectShouldBeVisible; ShouldBeVisible:=AForm.HandleObjectShouldBeVisible;
if (fsModal in AForm.FormState) and ShouldBeVisible and (AWindow<>nil) then
{$IFDEF GTK3DEBUGCORE}
//use this if pure SetCapture(0) does not work under wayland.
ReleaseInputGrab;
{$ENDIF}
Gtk3WidgetSet.SetCapture(0);
if ShouldBeVisible and not IsFormDesign(AForm) then
begin begin
AWindow^.set_type_hint(GDK_WINDOW_TYPE_HINT_DIALOG); if (AForm.FormStyle in fsAllStayOnTop) then
AWindow^.set_modal(True); begin
if AForm.FormStyle = fsSystemStayOnTop then
AWindow^.set_keep_above(True)
else
{$warning according to gtk3 docs this window should stay above application windows, but it is not so,
if we click onto form below this one it goes behind that form, so maybe set_keep_above(true) here too,
but it's behaviour in that case is fsSystemStayOnTop. Check under wayland !}
AWindow^.set_type_hint(GDK_WINDOW_TYPE_HINT_UTILITY);
end;
if (fsModal in AForm.FormState) then
begin
AWindow^.set_modal(True);
AWindow^.window^.set_modal_hint(true);
end;
AWindow^.realize;
end; end;
AGtk3Widget.Visible := ShouldBeVisible; AGtk3Widget.Visible := ShouldBeVisible;
if AGtk3Widget.Visible then if AGtk3Widget.Visible then
begin begin
if (fsModal in AForm.FormState) and (Application.ModalLevel > 0) and (AWindow<>nil) then if not IsFormDesign(AForm) and (fsModal in AForm.FormState) and (Application.ModalLevel > 0) then
begin begin
// DebugLn('TGtk3WSCustomForm.ShowHide ModalLevel=',dbgs(Application.ModalLevel),' Self=',dbgsName(AForm)); // DebugLn('TGtk3WSCustomForm.ShowHide ModalLevel=',dbgs(Application.ModalLevel),' Self=',dbgsName(AForm));
if Application.ModalLevel > 1 then for i := 0 to Screen.CustomFormZOrderCount - 1 do
begin begin
for i := 0 to Screen.CustomFormZOrderCount - 1 do OtherForm:=Screen.CustomFormsZOrdered[i];
// DebugLn('CustomFormZOrder[',dbgs(i),'].',dbgsName(OtherForm),' modal=',dbgs(fsModal in OtherForm.FormState));
if (OtherForm <> AForm) and
OtherForm.HandleAllocated then
begin begin
OtherForm:=Screen.CustomFormsZOrdered[i]; // DebugLn('TGtk3WSCustomForm.ShowHide setTransient for ',dbgsName(OtherForm));
// DebugLn('CustomFormZOrder[',dbgs(i),'].',dbgsName(OtherForm),' modal=',dbgs(fsModal in OtherForm.FormState)); OtherGtk3Window:=TGtk3Window(OtherForm.Handle);
if (OtherForm <> AForm) and if Gtk3IsGtkWindow(OtherGtk3Window.Widget) then
(fsModal in OtherForm.FormState) and
OtherForm.HandleAllocated then
begin begin
// DebugLn('TGtk3WSCustomForm.ShowHide setTransient for ',dbgsName(OtherForm)); AWindow^.set_transient_for(PGtkWindow(OtherGtk3Window.Widget));
OtherGtk3Window:=TGtk3Window(OtherForm.Handle); break;
if Gtk3IsGtkWindow(OtherGtk3Window.Widget) then
begin
AWindow^.set_transient_for(PGtkWindow(OtherGtk3Window.Widget));
break;
end;
end; end;
end; end;
end; end;
end; end;
if AWindow<>nil then
begin AWindow^.show_all;
AWindow^.show_all; AMask := AWindow^.window^.get_events;
AMask := AWindow^.window^.get_events; AWindow^.window^.set_events(GDK_ALL_EVENTS_MASK);
AWindow^.window^.set_events(GDK_ALL_EVENTS_MASK {AMask or GDK_POINTER_MOTION_MASK or GDK_POINTER_MOTION_HINT_MASK}); if not IsFormDesign(AForm) then
end; AWindow^.present;
end else end else
begin begin
if (fsModal in AForm.FormState) and (AWindow<>nil) then if not IsFormDesign(AForm) and (fsModal in AForm.FormState) then
begin begin
if AWindow^.transient_for <> nil then if AWindow^.transient_for <> nil then
begin
// DebugLn('TGtk3WSCustomForm.ShowHide removetransientsient for ',dbgsName(AForm));
AWindow^.set_transient_for(nil); AWindow^.set_transient_for(nil);
end;
end; end;
end; end;
end; end;
@ -406,7 +452,7 @@ begin
if not WSCheckHandleAllocated(ACustomForm, 'SetRealPopupParent') then if not WSCheckHandleAllocated(ACustomForm, 'SetRealPopupParent') then
Exit; Exit;
{$IFDEF GTK3DEBUGCORE} {$IFDEF GTK3DEBUGCORE}
DebugLn('TGtk3WSCustomForm.SetRealPopupParent'); DebugLn('TGtk3WSCustomForm.SetRealPopupParent AForm=',dbgsName(ACustomForm),' PopupParent=',dbgsName(APopupParent));
{$ENDIF} {$ENDIF}
end; end;