mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 16:19:28 +02:00
gtk2: fixed application deactivate on switch using alt-tab
This commit is contained in:
parent
8e72df6b62
commit
b66a32c36b
@ -971,7 +971,6 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
//DebugLn('GTKKillFocusCB ',DbgSName(TObject(Data)),' ',GetWidgetDebugReport(Widget));
|
//DebugLn('GTKKillFocusCB ',DbgSName(TObject(Data)),' ',GetWidgetDebugReport(Widget));
|
||||||
{$IFDEF VerboseFocus}
|
{$IFDEF VerboseFocus}
|
||||||
NeedShiftUpdateAfternFocus := True; // <- JRA: this doesn't look like simply log !!!
|
|
||||||
LCLObject:=TObject(data);
|
LCLObject:=TObject(data);
|
||||||
DebugLn(['GTKillFocusCB Widget=',DbgS(Widget),' Event^.theIn=',Event^._in,
|
DebugLn(['GTKillFocusCB Widget=',DbgS(Widget),' Event^.theIn=',Event^._in,
|
||||||
' LCLObject=',dbgsName(LCLobject)]);
|
' LCLObject=',dbgsName(LCLobject)]);
|
||||||
@ -1002,7 +1001,6 @@ begin
|
|||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
//DebugLn('GTKKillFocusCBAfter ',DbgSName(TObject(Data)),' ',GetWidgetDebugReport(Widget));
|
//DebugLn('GTKKillFocusCBAfter ',DbgSName(TObject(Data)),' ',GetWidgetDebugReport(Widget));
|
||||||
{$IFDEF VerboseFocus}
|
{$IFDEF VerboseFocus}
|
||||||
NeedShiftUpdateAfternFocus := True; // <- JRA: this doesn't look like simply log !!!
|
|
||||||
LCLObject:=TObject(data);
|
LCLObject:=TObject(data);
|
||||||
DebugLnEnter(['GTKillFocusCBAfter INIT Widget=',DbgS(Widget),' Event^.theIn=',Event^._in,
|
DebugLnEnter(['GTKillFocusCBAfter INIT Widget=',DbgS(Widget),' Event^.theIn=',Event^._in,
|
||||||
' LCLObject=',dbgsName(LCLObject)]);
|
' LCLObject=',dbgsName(LCLObject)]);
|
||||||
|
@ -325,7 +325,8 @@ type
|
|||||||
procedure HideAllHints;
|
procedure HideAllHints;
|
||||||
procedure RestoreAllHints;
|
procedure RestoreAllHints;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
procedure StartFocusTimer;
|
procedure StartAppFocusTimer;
|
||||||
|
procedure StopAppFocusTimer;
|
||||||
property AppActive: Boolean read GetAppActive write SetAppActive;
|
property AppActive: Boolean read GetAppActive write SetAppActive;
|
||||||
property IsLibraryInstance: Boolean read FIsLibraryInstance;
|
property IsLibraryInstance: Boolean read FIsLibraryInstance;
|
||||||
property GtkIsTerminated: Boolean read FGtkTerminated;
|
property GtkIsTerminated: Boolean read FGtkTerminated;
|
||||||
|
@ -2776,13 +2776,12 @@ function gtkAppFocusTimer({%H-}Data: gPointer):gBoolean; cdecl;
|
|||||||
// needed by app activate/deactivate
|
// needed by app activate/deactivate
|
||||||
begin
|
begin
|
||||||
Result := CallBackDefaultReturn;
|
Result := CallBackDefaultReturn;
|
||||||
|
TGtk2WidgetSet(WidgetSet).StopAppFocusTimer;
|
||||||
if TGtk2WidgetSet(WidgetSet).LastFocusIn = nil then
|
if TGtk2WidgetSet(WidgetSet).LastFocusIn = nil then
|
||||||
TGtk2WidgetSet(WidgetSet).AppActive := False;
|
TGtk2WidgetSet(WidgetSet).AppActive := False;
|
||||||
gtk_timeout_remove(TGtk2WidgetSet(WidgetSet).FocusTimer);
|
|
||||||
TGtk2WidgetSet(WidgetSet).FocusTimer := 0;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure TGtk2WidgetSet.StartFocusTimer;
|
procedure TGtk2WidgetSet.StartAppFocusTimer;
|
||||||
begin
|
begin
|
||||||
FLastFocusIn := nil;
|
FLastFocusIn := nil;
|
||||||
if FocusTimer <> 0 then
|
if FocusTimer <> 0 then
|
||||||
@ -2790,6 +2789,13 @@ begin
|
|||||||
FocusTimer := gtk_timeout_add(50, TGtkFunction(@gtkAppFocusTimer), nil);
|
FocusTimer := gtk_timeout_add(50, TGtkFunction(@gtkAppFocusTimer), nil);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGtk2WidgetSet.StopAppFocusTimer;
|
||||||
|
begin
|
||||||
|
if FocusTimer = 0 then exit;
|
||||||
|
gtk_timeout_remove(FocusTimer);
|
||||||
|
FocusTimer := 0;
|
||||||
|
end;
|
||||||
|
|
||||||
procedure TGtk2WidgetSet.InitStockItems;
|
procedure TGtk2WidgetSet.InitStockItems;
|
||||||
var
|
var
|
||||||
LogBrush: TLogBrush;
|
LogBrush: TLogBrush;
|
||||||
|
@ -269,31 +269,52 @@ begin
|
|||||||
GDK_FOCUS_CHANGE:
|
GDK_FOCUS_CHANGE:
|
||||||
begin
|
begin
|
||||||
ACtl := TWinControl(Data);
|
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 <sigh>.
|
||||||
if PGdkEventFocus(event)^._in = 0 then
|
if PGdkEventFocus(event)^._in = 0 then
|
||||||
begin
|
begin
|
||||||
{$IFDEF HASX}
|
{$IFDEF HASX}
|
||||||
XDisplay := gdk_display;
|
if ACtl.Parent<>nil then
|
||||||
XGetInputFocus(XDisplay, @Window, @RevertStatus);
|
begin
|
||||||
// Window - 1 is our frame !
|
XDisplay := gdk_display;
|
||||||
if (RevertStatus = RevertToParent) and
|
XGetInputFocus(XDisplay, @Window, @RevertStatus);
|
||||||
(GDK_WINDOW_XID(Widget^.Window) = Window - 1) then
|
// Window - 1 is our frame !
|
||||||
exit(True);
|
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}
|
{$ENDIF}
|
||||||
with Gtk2WidgetSet do
|
with Gtk2WidgetSet do
|
||||||
begin
|
begin
|
||||||
LastFocusOut := {%H-}PGtkWidget(ACtl.Handle);
|
LastFocusOut := {%H-}PGtkWidget(ACtl.Handle);
|
||||||
if LastFocusOut = LastFocusIn then
|
if LastFocusOut = LastFocusIn then
|
||||||
StartFocusTimer;
|
StartAppFocusTimer;
|
||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
with Gtk2WidgetSet do
|
with Gtk2WidgetSet do
|
||||||
begin
|
begin
|
||||||
|
StopAppFocusTimer;
|
||||||
LastFocusIn := {%H-}PGtkWidget(ACtl.Handle);
|
LastFocusIn := {%H-}PGtkWidget(ACtl.Handle);
|
||||||
if not AppActive then
|
if not AppActive then
|
||||||
AppActive := True;
|
AppActive := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
if GTK_IS_WINDOW(Widget) and
|
if GTK_IS_WINDOW(Widget) and
|
||||||
(g_object_get_data({%H-}PGObject(ACtl.Handle),'lcl_nonmodal_over_modal') <> nil) then
|
(g_object_get_data({%H-}PGObject(ACtl.Handle),'lcl_nonmodal_over_modal') <> nil) then
|
||||||
begin
|
begin
|
||||||
@ -308,9 +329,14 @@ end;
|
|||||||
|
|
||||||
class procedure TGtk2WSCustomForm.SetCallbacks(const AWidget: PGtkWidget;
|
class procedure TGtk2WSCustomForm.SetCallbacks(const AWidget: PGtkWidget;
|
||||||
const AWidgetInfo: PWidgetInfo);
|
const AWidgetInfo: PWidgetInfo);
|
||||||
|
var
|
||||||
|
aLCLObj: TObject;
|
||||||
|
aLCLControl: TWinControl;
|
||||||
begin
|
begin
|
||||||
TGtk2WSWinControl.SetCallbacks(PGtkObject(AWidget), TComponent(AWidgetInfo^.LCLObject));
|
aLCLObj:=AWidgetInfo^.LCLObject;
|
||||||
if (TWinControl(AWidgetInfo^.LCLObject).Parent = nil) and (TWinControl(AWidgetInfo^.LCLObject).ParentWindow = 0) then
|
aLCLControl:=TWinControl(aLCLObj);
|
||||||
|
TGtk2WSWinControl.SetCallbacks(PGtkObject(AWidget), aLCLControl);
|
||||||
|
if (aLCLControl.Parent = nil) and (aLCLControl.ParentWindow = 0) then
|
||||||
with TGTK2WidgetSet(Widgetset) do
|
with TGTK2WidgetSet(Widgetset) do
|
||||||
begin
|
begin
|
||||||
{$IFDEF HASX}
|
{$IFDEF HASX}
|
||||||
@ -318,18 +344,18 @@ begin
|
|||||||
// see http://bugs.freepascal.org/view.php?id=17523
|
// see http://bugs.freepascal.org/view.php?id=17523
|
||||||
if not compositeManagerRunning then
|
if not compositeManagerRunning then
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
SetCallback(LM_CONFIGUREEVENT, PGtkObject(AWidget), AWidgetInfo^.LCLObject);
|
SetCallback(LM_CONFIGUREEVENT, PGtkObject(AWidget), aLCLObj);
|
||||||
SetCallback(LM_CLOSEQUERY, PGtkObject(AWidget), AWidgetInfo^.LCLObject);
|
SetCallback(LM_CLOSEQUERY, PGtkObject(AWidget), aLCLObj);
|
||||||
SetCallBack(LM_ACTIVATE, PGtkObject(AWidget), AWidgetInfo^.LCLObject);
|
SetCallBack(LM_ACTIVATE, PGtkObject(AWidget), aLCLObj);
|
||||||
if (gtk_major_version = 2) and (gtk_minor_version <= 8) then
|
if (gtk_major_version = 2) and (gtk_minor_version <= 8) then
|
||||||
begin
|
begin
|
||||||
SetCallback(LM_HSCROLL, PGtkObject(AWidget), AWidgetInfo^.LCLObject);
|
SetCallback(LM_HSCROLL, PGtkObject(AWidget), aLCLObj);
|
||||||
SetCallback(LM_VSCROLL, PGtkObject(AWidget), AWidgetInfo^.LCLObject);
|
SetCallback(LM_VSCROLL, PGtkObject(AWidget), aLCLObj);
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
g_signal_connect(PGtkObject(AWidgetInfo^.CoreWidget), 'event',
|
g_signal_connect(PGtkObject(AWidgetInfo^.CoreWidget), 'event',
|
||||||
gtk_signal_func(@Gtk2FormEvent), AWidgetInfo^.LCLObject);
|
gtk_signal_func(@Gtk2FormEvent), aLCLObj);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
class function TGtk2WSCustomForm.CanFocus(const AWinControl: TWinControl
|
class function TGtk2WSCustomForm.CanFocus(const AWinControl: TWinControl
|
||||||
|
Loading…
Reference in New Issue
Block a user