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,6 +214,32 @@ 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;
@ -241,26 +267,50 @@ 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; end;
if (fsModal in AForm.FormState) then
begin
AWindow^.set_modal(True);
AWindow^.window^.set_modal_hint(true);
end;
AWindow^.realize;
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
begin
for i := 0 to Screen.CustomFormZOrderCount - 1 do for i := 0 to Screen.CustomFormZOrderCount - 1 do
begin begin
OtherForm:=Screen.CustomFormsZOrdered[i]; OtherForm:=Screen.CustomFormsZOrdered[i];
// DebugLn('CustomFormZOrder[',dbgs(i),'].',dbgsName(OtherForm),' modal=',dbgs(fsModal in OtherForm.FormState)); // DebugLn('CustomFormZOrder[',dbgs(i),'].',dbgsName(OtherForm),' modal=',dbgs(fsModal in OtherForm.FormState));
if (OtherForm <> AForm) and if (OtherForm <> AForm) and
(fsModal in OtherForm.FormState) and
OtherForm.HandleAllocated then OtherForm.HandleAllocated then
begin begin
// DebugLn('TGtk3WSCustomForm.ShowHide setTransient for ',dbgsName(OtherForm)); // DebugLn('TGtk3WSCustomForm.ShowHide setTransient for ',dbgsName(OtherForm));
@ -273,25 +323,21 @@ begin
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 {AMask or GDK_POINTER_MOTION_MASK or GDK_POINTER_MOTION_HINT_MASK}); AWindow^.window^.set_events(GDK_ALL_EVENTS_MASK);
end; if not IsFormDesign(AForm) then
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;
class procedure TGtk3WSCustomForm.CloseModal(const ACustomForm: TCustomForm); class procedure TGtk3WSCustomForm.CloseModal(const ACustomForm: TCustomForm);
begin begin
@ -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;