mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-20 12:59:16 +02:00
lcl: gtk2: moved singleton MenuWidget to TGtk2WidgetSet, do not interfere with gtk2 focus evtns fixing AppActive with Alt-Tab and switching to another workspace
This commit is contained in:
parent
a3b072a4cd
commit
163caebf0b
@ -678,7 +678,7 @@ begin
|
|||||||
and gtk_window_has_TopLevel_Focus(Window) then
|
and gtk_window_has_TopLevel_Focus(Window) then
|
||||||
begin
|
begin
|
||||||
// fake focus-out event
|
// fake focus-out event
|
||||||
{$IFDEF VerboseFocus}
|
{$IF defined(VerboseFocus) or defined(VerboseGtk2Focus)}
|
||||||
DebugLn('NOTE: Window with stalled focus found!, faking focus-out event');
|
DebugLn('NOTE: Window with stalled focus found!, faking focus-out event');
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
event := gdk_event_new(GDK_FOCUS_CHANGE);
|
event := gdk_event_new(GDK_FOCUS_CHANGE);
|
||||||
|
@ -272,10 +272,12 @@ type
|
|||||||
private
|
private
|
||||||
{$IFDEF HASX}
|
{$IFDEF HASX}
|
||||||
FDesktopWidget: PGtkWidget;
|
FDesktopWidget: PGtkWidget;
|
||||||
|
FMenuWidget: PGtkWidget;
|
||||||
FWSFrameRect: TRect;
|
FWSFrameRect: TRect;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
procedure Gtk2Create;
|
procedure Gtk2Create;
|
||||||
procedure Gtk2Destroy;
|
procedure Gtk2Destroy;
|
||||||
|
procedure SetMenuWidget(const AValue: PGtkWidget);
|
||||||
|
|
||||||
protected
|
protected
|
||||||
function GetAppHandle: TLCLHandle; override;
|
function GetAppHandle: TLCLHandle; override;
|
||||||
@ -334,6 +336,7 @@ type
|
|||||||
property LastFocusOut: PGtkWidget read FLastFocusOut write FLastFocusOut;
|
property LastFocusOut: PGtkWidget read FLastFocusOut write FLastFocusOut;
|
||||||
property MultiThreadingEnabled: boolean read FMultiThreadingEnabled;
|
property MultiThreadingEnabled: boolean read FMultiThreadingEnabled;
|
||||||
property KeyStateList: TFPList read FKeyStateList_;
|
property KeyStateList: TFPList read FKeyStateList_;
|
||||||
|
property MenuWidget: PGtkWidget read FMenuWidget write SetMenuWidget;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{$I gtk2listslh.inc}
|
{$I gtk2listslh.inc}
|
||||||
|
@ -1925,6 +1925,12 @@ begin
|
|||||||
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure TGtk2WidgetSet.SetMenuWidget(const AValue: PGtkWidget);
|
||||||
|
begin
|
||||||
|
if FMenuWidget=AValue then Exit;
|
||||||
|
FMenuWidget:=AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
{$ifdef Unix}
|
{$ifdef Unix}
|
||||||
|
|
||||||
{$IFDEF HASX}
|
{$IFDEF HASX}
|
||||||
@ -2759,6 +2765,9 @@ procedure TGtk2WidgetSet.SetAppActive(const AValue: Boolean);
|
|||||||
begin
|
begin
|
||||||
if AValue <> FAppActive then
|
if AValue <> FAppActive then
|
||||||
begin
|
begin
|
||||||
|
{$IFDEF VerboseGtk2Focus}
|
||||||
|
debugln(['TGtk2WidgetSet.SetAppActive ',AValue]);
|
||||||
|
{$ENDIF}
|
||||||
FAppActive := AValue;
|
FAppActive := AValue;
|
||||||
if FAppActive then
|
if FAppActive then
|
||||||
begin
|
begin
|
||||||
|
@ -273,36 +273,31 @@ begin
|
|||||||
// Application.Activate/Deactivate is done via a timer
|
// Application.Activate/Deactivate is done via a timer
|
||||||
// Every time a form looses the focus a timer is started
|
// Every time a form looses the focus a timer is started
|
||||||
// and every time focus is gained the timer is stopped.
|
// 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
|
||||||
// focus out
|
// focus out
|
||||||
//debugln(['Gtk2FormEvent focus out ',DbgSName(ACtl)]);
|
{$IFDEF VerboseGtk2Focus}
|
||||||
//if ACtl.Parent<>nil then
|
debugln(['Gtk2FormEvent focus out ',DbgSName(ACtl)]);
|
||||||
// debugln(['Gtk2FormEvent ACtl.Parent=',DbgSName(ACtl.Parent)]);
|
{$ENDIF}
|
||||||
|
|
||||||
// Test switch to another app via mouse, Alt-Tab, workspace. And test open popup menu click GetFocus.
|
// When touching this code:
|
||||||
|
// Test switching to another app via mouse, Alt-Tab, workspace.
|
||||||
|
// And test open popup menu then click and GetFocus.
|
||||||
|
|
||||||
{$IFDEF HASX}
|
{$IF defined(HASX) and defined(EnableKeepGtk2WidgetActivated)}
|
||||||
//if ACtl.Parent<>nil then
|
// MG: this code kept the gtk state activated, so that GetFocus
|
||||||
//begin
|
// returned the last focused form.
|
||||||
XDisplay := gdk_display;
|
// This broke AppActive when switching on Linux with Atl-Tab or to another Workspace
|
||||||
XGetInputFocus(XDisplay, @Window, @RevertStatus);
|
XDisplay := gdk_display;
|
||||||
// Window - 1 is our frame !
|
XGetInputFocus(XDisplay, @Window, @RevertStatus);
|
||||||
if (RevertStatus = RevertToParent) and
|
// Window - 1 is our frame !
|
||||||
(GDK_WINDOW_XID(Widget^.Window) = Window - 1) then
|
if (RevertStatus = RevertToParent) and
|
||||||
begin
|
(GDK_WINDOW_XID(Widget^.Window) = Window - 1) then
|
||||||
// Note: on LinuxMint switching via Alt-Tab to another window
|
begin
|
||||||
// generates RevertToParent.
|
// Note: on LinuxMint switching via Alt-Tab to another window
|
||||||
exit(True); // stop
|
// generates RevertToParent.
|
||||||
end;
|
exit(True); // stop
|
||||||
//end;
|
end;
|
||||||
{$ENDIF}
|
{$ENDIF}
|
||||||
with Gtk2WidgetSet do
|
with Gtk2WidgetSet do
|
||||||
begin
|
begin
|
||||||
@ -312,7 +307,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
end else
|
end else
|
||||||
begin
|
begin
|
||||||
//debugln(['Gtk2FormEvent focus in ',DbgSName(ACtl)]);
|
{$IFDEF VerboseGtk2Focus}
|
||||||
|
debugln(['Gtk2FormEvent focus in ',DbgSName(ACtl)]);
|
||||||
|
{$ENDIF}
|
||||||
with Gtk2WidgetSet do
|
with Gtk2WidgetSet do
|
||||||
begin
|
begin
|
||||||
StopAppFocusTimer;
|
StopAppFocusTimer;
|
||||||
|
@ -24,7 +24,7 @@ uses
|
|||||||
// RTL
|
// RTL
|
||||||
Classes, Types, glib2, gdk2, gtk2, math,
|
Classes, Types, glib2, gdk2, gtk2, math,
|
||||||
// LazUtils
|
// LazUtils
|
||||||
LazTracer,
|
LazTracer, LazLoggerBase,
|
||||||
// LCL
|
// LCL
|
||||||
Gtk2Int, Gtk2Proc, Gtk2Globals, Gtk2Def, Gtk2Extra,
|
Gtk2Int, Gtk2Proc, Gtk2Globals, Gtk2Def, Gtk2Extra,
|
||||||
LCLType, LCLIntf, InterfaceBase, WSMenus, LMessages, Graphics, Menus, Forms;
|
LCLType, LCLIntf, InterfaceBase, WSMenus, LMessages, Graphics, Menus, Forms;
|
||||||
@ -79,9 +79,6 @@ implementation
|
|||||||
|
|
||||||
{$I gtk2defines.inc}
|
{$I gtk2defines.inc}
|
||||||
|
|
||||||
var
|
|
||||||
MenuWidget: PGtkWidget = nil;
|
|
||||||
|
|
||||||
function Gtk2MenuItemButtonPress(widget: PGtkWidget; event: PGdkEventButton;
|
function Gtk2MenuItemButtonPress(widget: PGtkWidget; event: PGdkEventButton;
|
||||||
{%H-}user_data: gpointer): gboolean; cdecl;
|
{%H-}user_data: gpointer): gboolean; cdecl;
|
||||||
var
|
var
|
||||||
@ -387,7 +384,7 @@ end;
|
|||||||
class procedure TGtk2WSMenuItem.SetShortCut(const AMenuItem: TMenuItem;
|
class procedure TGtk2WSMenuItem.SetShortCut(const AMenuItem: TMenuItem;
|
||||||
const ShortCutK1, ShortCutK2: TShortCut);
|
const ShortCutK1, ShortCutK2: TShortCut);
|
||||||
//var
|
//var
|
||||||
//MenuWidget: PGtkMenuItem;
|
//aMenuWidget: PGtkMenuItem;
|
||||||
//accel_path: String;
|
//accel_path: String;
|
||||||
//CurKey: Word;
|
//CurKey: Word;
|
||||||
//CurShift: TShiftState;
|
//CurShift: TShiftState;
|
||||||
@ -398,8 +395,8 @@ begin
|
|||||||
UpdateInnerMenuItem(AMenuItem, {%H-}PGTKWidget(AMenuItem.Handle), ShortCutK1, ShortCutK2);
|
UpdateInnerMenuItem(AMenuItem, {%H-}PGTKWidget(AMenuItem.Handle), ShortCutK1, ShortCutK2);
|
||||||
|
|
||||||
{ // Gets the inner widgets. They should already be created by now
|
{ // Gets the inner widgets. They should already be created by now
|
||||||
MenuWidget := PGtkMenuItem(AMenuItem.Handle);
|
aMenuWidget := PGtkMenuItem(AMenuItem.Handle);
|
||||||
if (MenuWidget=nil) then Exit;
|
if (aMenuWidget=nil) then Exit;
|
||||||
// Converts the shortcut to a gtk friendly format and sets it
|
// Converts the shortcut to a gtk friendly format and sets it
|
||||||
ShortCutToKey(NewShortCut, CurKey, CurShift);
|
ShortCutToKey(NewShortCut, CurKey, CurShift);
|
||||||
accel_path := 'LCLApp/Menu/' + GetAcceleratorString(CurKey, CurShift);
|
accel_path := 'LCLApp/Menu/' + GetAcceleratorString(CurKey, CurShift);
|
||||||
@ -628,13 +625,15 @@ end;
|
|||||||
|
|
||||||
procedure gtkWSPopupMenuDeactivate(widget: PGtkWidget; data: gPointer); cdecl;
|
procedure gtkWSPopupMenuDeactivate(widget: PGtkWidget; data: gPointer); cdecl;
|
||||||
begin
|
begin
|
||||||
if widget = MenuWidget then
|
{$IFDEF VerboseGtk2Focus}
|
||||||
MenuWidget := nil;
|
DebugLn('gtkWSPopupMenuDeactivate ');
|
||||||
|
{$ENDIF}
|
||||||
|
if widget = TGtk2WidgetSet(WidgetSet).MenuWidget then
|
||||||
|
TGtk2WidgetSet(WidgetSet).MenuWidget := nil;
|
||||||
if data <> nil then
|
if data <> nil then
|
||||||
g_idle_add(@gtkWSPopupDelayedClose, Pointer(PWidgetInfo(data)^.LCLObject));
|
g_idle_add(@gtkWSPopupDelayedClose, Pointer(PWidgetInfo(data)^.LCLObject));
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
class procedure TGtk2WSPopupMenu.SetCallbacks(const AGtkWidget: PGtkWidget;
|
class procedure TGtk2WSPopupMenu.SetCallbacks(const AGtkWidget: PGtkWidget;
|
||||||
const AWidgetInfo: PWidgetInfo);
|
const AWidgetInfo: PWidgetInfo);
|
||||||
begin
|
begin
|
||||||
@ -663,8 +662,9 @@ var
|
|||||||
APoint: TPoint;
|
APoint: TPoint;
|
||||||
AProc: Pointer;
|
AProc: Pointer;
|
||||||
WidgetInfo: PWidgetInfo;
|
WidgetInfo: PWidgetInfo;
|
||||||
|
MenuWidget: PGtkWidget;
|
||||||
begin
|
begin
|
||||||
if MenuWidget<>nil then //cannot popup when another popup menu is visible
|
if TGtk2WidgetSet(WidgetSet).MenuWidget<>nil then //cannot popup when another popup menu is visible
|
||||||
Exit;
|
Exit;
|
||||||
|
|
||||||
ReleaseMouseCapture;
|
ReleaseMouseCapture;
|
||||||
@ -679,8 +679,14 @@ begin
|
|||||||
// MenuWidget can be either GtkMenu or GtkMenuItem submenu
|
// MenuWidget can be either GtkMenu or GtkMenuItem submenu
|
||||||
if GTK_IS_MENU_ITEM(MenuWidget) then
|
if GTK_IS_MENU_ITEM(MenuWidget) then
|
||||||
MenuWidget := gtk_menu_item_get_submenu(PGtkMenuItem(MenuWidget));
|
MenuWidget := gtk_menu_item_get_submenu(PGtkMenuItem(MenuWidget));
|
||||||
|
|
||||||
|
TGtk2WidgetSet(WidgetSet).MenuWidget:=MenuWidget;
|
||||||
gtk_menu_popup(PGtkMenu(MenuWidget), nil, nil, TGtkMenuPositionFunc(AProc),
|
gtk_menu_popup(PGtkMenu(MenuWidget), nil, nil, TGtkMenuPositionFunc(AProc),
|
||||||
WidgetInfo, 0, gtk_get_current_event_time());
|
WidgetInfo, 0, gtk_get_current_event_time());
|
||||||
|
TGtk2WidgetSet(WidgetSet).LastFocusIn:=MenuWidget;
|
||||||
|
{$IFDEF VerboseGtk2Focus}
|
||||||
|
debugln('TGtk2WSPopupMenu.Popup REPEAT...');
|
||||||
|
{$ENDIF}
|
||||||
repeat
|
repeat
|
||||||
try
|
try
|
||||||
WidgetSet.AppProcessMessages; // process all events
|
WidgetSet.AppProcessMessages; // process all events
|
||||||
@ -694,6 +700,9 @@ begin
|
|||||||
break;
|
break;
|
||||||
Application.Idle(true);
|
Application.Idle(true);
|
||||||
until False;
|
until False;
|
||||||
|
{$IFDEF VerboseGtk2Focus}
|
||||||
|
debugln('TGtk2WSPopupMenu.Popup END');
|
||||||
|
{$ENDIF}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end.
|
end.
|
||||||
|
Loading…
Reference in New Issue
Block a user