diff --git a/lcl/interfaces/gtk/gtkwidgetset.inc b/lcl/interfaces/gtk/gtkwidgetset.inc index 0eea2508ee..b9263116b2 100644 --- a/lcl/interfaces/gtk/gtkwidgetset.inc +++ b/lcl/interfaces/gtk/gtkwidgetset.inc @@ -1394,9 +1394,14 @@ begin begin FAppActive := AValue; if FAppActive then - Application.IntfAppActivate - else + begin + Application.IntfAppActivate; + AppRestoreStayOnTopFlags(False); + end else + begin Application.IntfAppDeactivate; + AppRemoveStayOnTopFlags(False); + end; end; end; diff --git a/lcl/interfaces/gtk2/gtk2int.pas b/lcl/interfaces/gtk2/gtk2int.pas index ca370c5c7c..4215973ca4 100644 --- a/lcl/interfaces/gtk2/gtk2int.pas +++ b/lcl/interfaces/gtk2/gtk2int.pas @@ -34,7 +34,7 @@ interface {$I gtkdefines.inc} uses - Types, Classes, SysUtils, Math, + Types, Classes, SysUtils, Math, maps, {$IfNDef GTK2_2} {$IfDef HasX} XLib, X, //XUtil, @@ -52,6 +52,8 @@ type { TGtk2WidgetSet } TGtk2WidgetSet = class(TGtkWidgetSet) + private + StayOnTopList: TMap; protected procedure AppendText(Sender: TObject; Str: PChar); function GetText(Sender: TComponent; var Text: String): Boolean; @@ -68,6 +70,8 @@ type procedure AppMinimize; override; procedure AppRestore; override; function AppHandle: THandle; override; + function AppRemoveStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; override; + function AppRestoreStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; override; procedure SetCallbackEx(const AMsg: LongInt; const AGTKObject: PGTKObject; const ALCLObject: TObject; Direct: Boolean);override; procedure SetCommonCallbacks(const AGTKObject: PGTKObject; const ALCLObject: TObject); override; diff --git a/lcl/interfaces/gtk2/gtk2widgetset.inc b/lcl/interfaces/gtk2/gtk2widgetset.inc index 031ee70163..9cda987273 100644 --- a/lcl/interfaces/gtk2/gtk2widgetset.inc +++ b/lcl/interfaces/gtk2/gtk2widgetset.inc @@ -565,6 +565,7 @@ end; constructor TGtk2WidgetSet.Create; begin inherited Create; + StayOnTopList := nil; im_context:=gtk_im_multicontext_new; g_signal_connect (G_OBJECT (im_context), 'commit', G_CALLBACK (@gtk_commit_cb), nil); @@ -575,6 +576,11 @@ begin g_object_unref(im_context); im_context:=nil; im_context_widget:=nil; + if StayOnTopList <> nil then + begin + StayOnTopList.Free; + StayOnTopList := nil; + end; inherited Destroy; end; @@ -653,6 +659,77 @@ begin {$endif} end; +type + TGtk2TempFormStyleSet = Set of TFormStyle; +const + TGtk2TopForms: Array[Boolean] of TGtk2TempFormStyleSet = (fsAllNonSystemStayOnTop, + fsAllStayOnTop); + +function TGtk2WidgetSet.AppRemoveStayOnTopFlags(const ASystemTopAlso: Boolean + ): Boolean; +var + i: Integer; + AForm: TCustomForm; + W: PGtkWidget; + Flags: TGdkWindowState; +begin + Result := True; + if StayOnTopList = nil then + StayOnTopList := TMap.Create(TMapIdType(ituPtrSize), SizeOf(TGtkWidget)); + for i := 0 to Screen.CustomFormZOrderCount - 1 do + begin + AForm := Screen.CustomFormsZOrdered[i]; + if AForm.HandleAllocated then + begin + W := PGtkWidget(AForm.Handle); + Flags := gdk_window_get_state(W^.Window); + if (AForm.Parent = nil) and + (AForm.FormStyle in TGtk2TopForms[ASystemTopAlso]) and + GTK_WIDGET_VISIBLE(W) and + not gtk_window_get_modal(PGtkWindow(W)) and + (Flags and GDK_WINDOW_STATE_ICONIFIED = 0) then + begin + gdk_window_set_keep_above(W^.Window, False); + if not StayOnTopList.HasId(W) then + StayOnTopList.Add(W, W); + end; + end; + end; +end; + +function TGtk2WidgetSet.AppRestoreStayOnTopFlags(const ASystemTopAlso: Boolean + ): Boolean; +var + i: Integer; + AForm: TCustomForm; + W: PGtkWidget; + Flags: TGdkWindowState; +begin + Result := True; + if StayOnTopList = nil then + exit; + for i := Screen.CustomFormZOrderCount - 1 downto 0 do + begin + AForm := Screen.CustomFormsZOrdered[i]; + if AForm.HandleAllocated then + begin + W := PGtkWidget(AForm.Handle); + Flags := gdk_window_get_state(W^.Window); + if (AForm.Parent = nil) and + (AForm.FormStyle in TGtk2TopForms[ASystemTopAlso]) and + GTK_WIDGET_VISIBLE(W) and + not gtk_window_get_modal(PGtkWindow(W)) and + (Flags and GDK_WINDOW_STATE_ICONIFIED = 0) then + begin + if StayOnTopList.HasId(W) then + gdk_window_set_keep_above(W^.Window, True); + end; + end; + end; + StayOnTopList.Free; + StayOnTopList := nil; +end; + {$IFDEF ASSERT_IS_ON} {$UNDEF ASSERT_IS_ON} {$C-}