diff --git a/lcl/interfaces/gtk2/gtk2callback.inc b/lcl/interfaces/gtk2/gtk2callback.inc index b00d947b62..aa40834d53 100644 --- a/lcl/interfaces/gtk2/gtk2callback.inc +++ b/lcl/interfaces/gtk2/gtk2callback.inc @@ -971,7 +971,6 @@ begin {$ENDIF} //DebugLn('GTKKillFocusCB ',DbgSName(TObject(Data)),' ',GetWidgetDebugReport(Widget)); {$IFDEF VerboseFocus} - NeedShiftUpdateAfternFocus := True; // <- JRA: this doesn't look like simply log !!! LCLObject:=TObject(data); DebugLn(['GTKillFocusCB Widget=',DbgS(Widget),' Event^.theIn=',Event^._in, ' LCLObject=',dbgsName(LCLobject)]); @@ -1002,7 +1001,6 @@ begin {$ENDIF} //DebugLn('GTKKillFocusCBAfter ',DbgSName(TObject(Data)),' ',GetWidgetDebugReport(Widget)); {$IFDEF VerboseFocus} - NeedShiftUpdateAfternFocus := True; // <- JRA: this doesn't look like simply log !!! LCLObject:=TObject(data); DebugLnEnter(['GTKillFocusCBAfter INIT Widget=',DbgS(Widget),' Event^.theIn=',Event^._in, ' LCLObject=',dbgsName(LCLObject)]); diff --git a/lcl/interfaces/gtk2/gtk2int.pas b/lcl/interfaces/gtk2/gtk2int.pas index 6470d3d6d1..5f572fbaff 100644 --- a/lcl/interfaces/gtk2/gtk2int.pas +++ b/lcl/interfaces/gtk2/gtk2int.pas @@ -325,7 +325,8 @@ type procedure HideAllHints; procedure RestoreAllHints; {$ENDIF} - procedure StartFocusTimer; + procedure StartAppFocusTimer; + procedure StopAppFocusTimer; property AppActive: Boolean read GetAppActive write SetAppActive; property IsLibraryInstance: Boolean read FIsLibraryInstance; property GtkIsTerminated: Boolean read FGtkTerminated; diff --git a/lcl/interfaces/gtk2/gtk2widgetset.inc b/lcl/interfaces/gtk2/gtk2widgetset.inc index d4fde8c26b..5835859da1 100644 --- a/lcl/interfaces/gtk2/gtk2widgetset.inc +++ b/lcl/interfaces/gtk2/gtk2widgetset.inc @@ -2776,13 +2776,12 @@ function gtkAppFocusTimer({%H-}Data: gPointer):gBoolean; cdecl; // needed by app activate/deactivate begin Result := CallBackDefaultReturn; + TGtk2WidgetSet(WidgetSet).StopAppFocusTimer; if TGtk2WidgetSet(WidgetSet).LastFocusIn = nil then TGtk2WidgetSet(WidgetSet).AppActive := False; - gtk_timeout_remove(TGtk2WidgetSet(WidgetSet).FocusTimer); - TGtk2WidgetSet(WidgetSet).FocusTimer := 0; end; -procedure TGtk2WidgetSet.StartFocusTimer; +procedure TGtk2WidgetSet.StartAppFocusTimer; begin FLastFocusIn := nil; if FocusTimer <> 0 then @@ -2790,6 +2789,13 @@ begin FocusTimer := gtk_timeout_add(50, TGtkFunction(@gtkAppFocusTimer), nil); end; +procedure TGtk2WidgetSet.StopAppFocusTimer; +begin + if FocusTimer = 0 then exit; + gtk_timeout_remove(FocusTimer); + FocusTimer := 0; +end; + procedure TGtk2WidgetSet.InitStockItems; var LogBrush: TLogBrush; diff --git a/lcl/interfaces/gtk2/gtk2wsforms.pp b/lcl/interfaces/gtk2/gtk2wsforms.pp index 8c0c327d4c..bcc30ecbd7 100644 --- a/lcl/interfaces/gtk2/gtk2wsforms.pp +++ b/lcl/interfaces/gtk2/gtk2wsforms.pp @@ -269,31 +269,52 @@ begin GDK_FOCUS_CHANGE: begin ACtl := TWinControl(Data); + + // Application.Activate/Deactivate is done via a timer + // Every time a form looses the focus a timer is started + // and every time focus is gained the timer is stopped. + // Note: It seems gtk2 itself does not always detect focus lost + // For example in LinuxMint switching from a TEdit using Alt-Tab to another + // app generates a focus out, but gtk2 still shows the TEdit focused + // with blinking cursor. + // Switching focus using the mouse to another app, also generates + // a focus out, and gtk2 hides the blinking cursor and focus coloring. + // Switching to another workspace does not generate a focus out event . if PGdkEventFocus(event)^._in = 0 then begin {$IFDEF HASX} - XDisplay := gdk_display; - XGetInputFocus(XDisplay, @Window, @RevertStatus); - // Window - 1 is our frame ! - if (RevertStatus = RevertToParent) and - (GDK_WINDOW_XID(Widget^.Window) = Window - 1) then - exit(True); + if ACtl.Parent<>nil then + begin + XDisplay := gdk_display; + XGetInputFocus(XDisplay, @Window, @RevertStatus); + // Window - 1 is our frame ! + if (RevertStatus = RevertToParent) and + (GDK_WINDOW_XID(Widget^.Window) = Window - 1) then + begin + // Note: on LinuxMint switching via Alt-Tab to another window + // generates RevertToParent. The above + // + exit(True); + end; + end; {$ENDIF} with Gtk2WidgetSet do begin LastFocusOut := {%H-}PGtkWidget(ACtl.Handle); if LastFocusOut = LastFocusIn then - StartFocusTimer; + StartAppFocusTimer; end; end else begin with Gtk2WidgetSet do begin + StopAppFocusTimer; LastFocusIn := {%H-}PGtkWidget(ACtl.Handle); if not AppActive then AppActive := True; end; end; + if GTK_IS_WINDOW(Widget) and (g_object_get_data({%H-}PGObject(ACtl.Handle),'lcl_nonmodal_over_modal') <> nil) then begin @@ -308,9 +329,14 @@ end; class procedure TGtk2WSCustomForm.SetCallbacks(const AWidget: PGtkWidget; const AWidgetInfo: PWidgetInfo); +var + aLCLObj: TObject; + aLCLControl: TWinControl; begin - TGtk2WSWinControl.SetCallbacks(PGtkObject(AWidget), TComponent(AWidgetInfo^.LCLObject)); - if (TWinControl(AWidgetInfo^.LCLObject).Parent = nil) and (TWinControl(AWidgetInfo^.LCLObject).ParentWindow = 0) then + aLCLObj:=AWidgetInfo^.LCLObject; + aLCLControl:=TWinControl(aLCLObj); + TGtk2WSWinControl.SetCallbacks(PGtkObject(AWidget), aLCLControl); + if (aLCLControl.Parent = nil) and (aLCLControl.ParentWindow = 0) then with TGTK2WidgetSet(Widgetset) do begin {$IFDEF HASX} @@ -318,18 +344,18 @@ begin // see http://bugs.freepascal.org/view.php?id=17523 if not compositeManagerRunning then {$ENDIF} - SetCallback(LM_CONFIGUREEVENT, PGtkObject(AWidget), AWidgetInfo^.LCLObject); - SetCallback(LM_CLOSEQUERY, PGtkObject(AWidget), AWidgetInfo^.LCLObject); - SetCallBack(LM_ACTIVATE, PGtkObject(AWidget), AWidgetInfo^.LCLObject); + SetCallback(LM_CONFIGUREEVENT, PGtkObject(AWidget), aLCLObj); + SetCallback(LM_CLOSEQUERY, PGtkObject(AWidget), aLCLObj); + SetCallBack(LM_ACTIVATE, PGtkObject(AWidget), aLCLObj); if (gtk_major_version = 2) and (gtk_minor_version <= 8) then begin - SetCallback(LM_HSCROLL, PGtkObject(AWidget), AWidgetInfo^.LCLObject); - SetCallback(LM_VSCROLL, PGtkObject(AWidget), AWidgetInfo^.LCLObject); + SetCallback(LM_HSCROLL, PGtkObject(AWidget), aLCLObj); + SetCallback(LM_VSCROLL, PGtkObject(AWidget), aLCLObj); end; end; g_signal_connect(PGtkObject(AWidgetInfo^.CoreWidget), 'event', - gtk_signal_func(@Gtk2FormEvent), AWidgetInfo^.LCLObject); + gtk_signal_func(@Gtk2FormEvent), aLCLObj); end; class function TGtk2WSCustomForm.CanFocus(const AWinControl: TWinControl