diff --git a/lcl/interfaces/gtk/gtkcallback.inc b/lcl/interfaces/gtk/gtkcallback.inc index dc4868362a..120e659826 100644 --- a/lcl/interfaces/gtk/gtkcallback.inc +++ b/lcl/interfaces/gtk/gtkcallback.inc @@ -1976,6 +1976,7 @@ function gtksize_allocateCB(widget: PGtkWidget; size: pGtkAllocation; var w, h: Gint; {$ENDIF} + begin Result := CallBackDefaultReturn; @@ -1992,6 +1993,18 @@ begin RaiseGDBException(''); exit; end; + {$IFDEF Gtk2} + // do not send msg to LCL if we are shown after hide, setVisible will + // do that. + if TObject(Data) is TForm then + begin + with GetWidgetInfo(Widget)^.FormSavedPos do + begin + if (X <> -10000) and (Y <> -10000) then + exit; + end; + end; + {$ENDIF} {$IFDEF VerboseSizeMsg} w:=0; h:=0; @@ -2037,7 +2050,8 @@ begin Result := CallBackDefaultReturn; if (Widget=nil) or (Size=nil) then ; - if (TObject(Data) is TWinControl) then begin + if (TObject(Data) is TWinControl) then + begin {$IFDEF VerboseSizeMsg} DebugLn('gtksize_allocate_client: ', TControl(Data).Name,':',TControl(Data).ClassName, diff --git a/lcl/interfaces/gtk/gtkdef.pp b/lcl/interfaces/gtk/gtkdef.pp index 4ee7828efe..823d97ec3d 100644 --- a/lcl/interfaces/gtk/gtkdef.pp +++ b/lcl/interfaces/gtk/gtkdef.pp @@ -481,6 +481,8 @@ type UserData: Pointer; FormBorderStyle: Integer; // used only by forms FormWindowState: TGdkEventWindowState; // used only by forms to stop infinite loops eg. issue #16505 + FormSavedPos: TPoint; // used only by forms - saved LCL Left & Top if form hidden eg. issue #15417 + // so later when we call show, it's restored to it's original position end; //TODO: remove diff --git a/lcl/interfaces/gtk/gtkwidgetset.inc b/lcl/interfaces/gtk/gtkwidgetset.inc index 33e901ead0..0eea2508ee 100644 --- a/lcl/interfaces/gtk/gtkwidgetset.inc +++ b/lcl/interfaces/gtk/gtkwidgetset.inc @@ -3699,7 +3699,8 @@ begin LM_WINDOWPOSCHANGED: //LM_SIZEALLOCATE, LM_RESIZE : begin ConnectSenderSignal(gObject, 'size-allocate', @gtksize_allocateCB); - if gObject<>gFixed then begin + if gObject<>gFixed then + begin ConnectSenderSignal(gFixed, 'size-allocate', @gtksize_allocate_client); end; end; @@ -4350,6 +4351,10 @@ var AWindow: PGdkWindow; ACustomForm: TCustomForm; {$IFDEF GTK2} + {$IFDEF VerboseFormPositioning} + X1, Y1: gint; // current gdk_window_root_origin + {$ENDIF} + SavedOrigin: TPoint; CurWindowState: TWindowState; {$ENDIF} begin @@ -4431,7 +4436,41 @@ begin if gtk_widget_visible(SenderWidget) then exit; + {$IFDEF GTK2} + // we must restore Left & Top coords here to prevent flickering + if (ACustomForm <> nil) and + (ACustomForm.Parent = nil) and + (ACustomForm.ParentWindow = 0) and + (ACustomForm is TForm) and // be sure that we are not THintWindow ! + (ACustomForm.BorderStyle <> bsNone) and + not (ACustomForm.FormStyle in [fsMDIChild, fsSplash]) then + begin + if (ACustomForm.WindowState <> wsMinimized) then + begin + SavedOrigin := GetWidgetInfo(SenderWidget)^.FormSavedPos; + if (SavedOrigin.X <> -10000) and (SavedOrigin.Y <> -10000) then + begin + {$IFDEF VerboseFormPositioning} + gdk_window_get_root_origin(SenderWidget^.window, @X1, @Y1); + DebugLn('VFP [TGtkWidgetSet.ShowHide] B ', + LCLControl.Name,':',LCLControl.ClassName, + ' Window=',dbgs(GetControlWindow(SenderWidget)<>nil), + ' RESTORE FORMSAVEDPOS CURRENT X=',dbgs(X1),' Y=',dbgs(Y1), + ' SAVED X=',dbgs(SavedOrigin.X),' Y=',dbgs(SavedOrigin.Y)); + {$ENDIF} + with SavedOrigin do + gtk_window_move(PGtkWindow(SenderWidget), X, Y); + SavedOrigin.X := -10000; + SavedOrigin.Y := -10000; + GetWidgetInfo(SenderWidget)^.FormSavedPos := SavedOrigin; + end; + end; + + end; + {$ENDIF} + gtk_widget_show(SenderWidget); + {$IFDEF GTK2} if (ACustomForm <> nil) and (ACustomForm.Parent = nil) and @@ -4453,13 +4492,30 @@ begin {$ENDIF} end else begin - if (ACustomForm<>nil) then begin + + if (ACustomForm<>nil) then UnshareWindowAccelGroups(SenderWidget); - end; if not gtk_widget_visible(SenderWidget) then exit; + {$IFDEF GTK2} + // save previous position + if ACustomForm <> nil then + begin + if (ACustomForm is TForm) and + not (ACustomForm.FormStyle in [fsMDIChild, fsSplash]) + and (ACustomForm.BorderStyle <> bsNone) then + begin + with GetWidgetInfo(SenderWidget)^.FormSavedPos do + begin + X := ACustomForm.Left; + Y := ACustomForm.Top; + end; + end; + end; + {$ENDIF} + gtk_widget_hide(SenderWidget); if GtkWidgetIsA(SenderWidget,GTK_TYPE_WINDOW) then begin diff --git a/lcl/interfaces/gtk2/gtk2wsforms.pp b/lcl/interfaces/gtk2/gtk2wsforms.pp index f383104a47..f0644c9c62 100644 --- a/lcl/interfaces/gtk2/gtk2wsforms.pp +++ b/lcl/interfaces/gtk2/gtk2wsforms.pp @@ -317,6 +317,14 @@ begin FillChar(WidgetInfo^.FormWindowState, SizeOf(WidgetInfo^.FormWindowState), #0); WidgetInfo^.FormWindowState.new_window_state := GDK_WINDOW_STATE_WITHDRAWN; + // FormRootOrigin is used only to save and restore LCL's Left & Top + // in case when form is hidden and then shown again ! + with WidgetInfo^.FormSavedPos do + begin + X := -10000; + Y := -10000; + end; + Box := CreateFormContents(ACustomForm, P, WidgetInfo); gtk_container_add(PGtkContainer(P), Box);