mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-03 22:27:10 +01:00
qt: use application FocusChanged slot to catch focus change events instead of listening for focus events of individual widgets. This new way should give better feedback from qt about focus changes.
git-svn-id: trunk@14361 -
This commit is contained in:
parent
fea0292e3d
commit
f7c7ce2ff8
@ -24,7 +24,7 @@
|
||||
|
||||
Sets the owner of this canvas
|
||||
------------------------------------------------------------------------------}
|
||||
Procedure TControlCanvas.SetControl(AControl: TControl);
|
||||
procedure TControlCanvas.SetControl(AControl: TControl);
|
||||
begin
|
||||
if FControl <> AControl then
|
||||
begin
|
||||
|
||||
@ -55,6 +55,10 @@ type
|
||||
private
|
||||
App: QApplicationH;
|
||||
SavedDCList: TList;
|
||||
// global hooks
|
||||
FAppEvenFilterHook: QObject_hookH;
|
||||
FAppFocusChangedHook: QApplication_hookH;
|
||||
|
||||
FOldFocusWidget: QWidgetH;
|
||||
FDockImage: QRubberBandH;
|
||||
FDragImageList: QWidgetH;
|
||||
@ -75,6 +79,7 @@ type
|
||||
|
||||
function CreateThemeServices: TThemeServices; override;
|
||||
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
|
||||
procedure FocusChanged(old: QWidgetH; now: QWidgetH); cdecl;
|
||||
procedure OnWakeMainThread(Sender: TObject);
|
||||
public
|
||||
function LCLPlatform: TLCLPlatform; override;
|
||||
@ -242,6 +247,22 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
function GetFirstQtObjectFromWidgetH(WidgetH: QWidgetH): TQtWidget;
|
||||
begin
|
||||
Result := nil;
|
||||
if WidgetH = nil then
|
||||
Exit;
|
||||
repeat
|
||||
Result := QtObjectFromWidgetH(WidgetH);
|
||||
if Result = nil then
|
||||
begin
|
||||
WidgetH := QWidget_parentWidget(WidgetH);
|
||||
if WidgetH = nil then
|
||||
break;
|
||||
end;
|
||||
until Result <> nil;
|
||||
end;
|
||||
|
||||
{$I qtobject.inc}
|
||||
{$I qtwinapi.inc}
|
||||
{$I qtlclintf.inc}
|
||||
|
||||
@ -97,24 +97,26 @@ end;
|
||||
procedure TQtWidgetSet.AppInit(var ScreenInfo: TScreenInfo);
|
||||
var
|
||||
Method: TMethod;
|
||||
FHook: QObject_hookH;
|
||||
ScreenDC: HDC;
|
||||
begin
|
||||
App := QApplication_Create(@argc, argv);
|
||||
WakeMainThread := @OnWakeMainThread;
|
||||
|
||||
FOldFocusWidget := nil;
|
||||
|
||||
|
||||
{
|
||||
check whether this hook crashes on linux & darwin and why it is so
|
||||
we need this hook to catch release messages
|
||||
}
|
||||
// install global event filter
|
||||
FHook := QObject_hook_create(App);
|
||||
FAppEvenFilterHook := QObject_hook_create(App);
|
||||
TEventFilterMethod(Method) := @EventFilter;
|
||||
QObject_hook_hook_events(FHook, Method);
|
||||
QObject_hook_hook_events(FAppEvenFilterHook, Method);
|
||||
|
||||
// install focus change slot
|
||||
FAppFocusChangedHook := QApplication_hook_create(App);
|
||||
QApplication_focusChanged_Event(Method) := @FocusChanged;
|
||||
QApplication_hook_hook_focusChanged(FAppFocusChangedHook, Method);
|
||||
|
||||
ScreenDC := GetDC(0);
|
||||
try
|
||||
@ -187,6 +189,10 @@ end;
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TQtWidgetSet.AppTerminate;
|
||||
begin
|
||||
// free hooks
|
||||
QObject_hook_destroy(FAppEvenFilterHook);
|
||||
QApplication_hook_destroy(FAppFocusChangedHook);
|
||||
|
||||
AppProcessMessages; // process pending messages since there can be release messages
|
||||
QCoreApplication_quit;
|
||||
end;
|
||||
@ -299,6 +305,32 @@ begin
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TQtWidgetSet.FocusChanged(old: QWidgetH; now: QWidgetH); cdecl;
|
||||
var
|
||||
OldWidget, NewWidget: TQtWidget;
|
||||
Msg: TLMessage;
|
||||
begin
|
||||
OldWidget := GetFirstQtObjectFromWidgetH(old);
|
||||
NewWidget := GetFirstQtObjectFromWidgetH(now);
|
||||
|
||||
if OldWidget = NewWidget then
|
||||
Exit;
|
||||
|
||||
FillChar(Msg, SizeOf(Msg), 0);
|
||||
if OldWidget <> nil then
|
||||
begin
|
||||
Msg.msg := LM_KILLFOCUS;
|
||||
Msg.wParam := PtrUInt(NewWidget);
|
||||
OldWidget.DeliverMessage(Msg);
|
||||
end;
|
||||
if NewWidget <> nil then
|
||||
begin
|
||||
Msg.msg := LM_SETFOCUS;
|
||||
Msg.wParam := PtrUInt(OldWidget);
|
||||
NewWidget.DeliverMessage(Msg);
|
||||
end;
|
||||
end;
|
||||
|
||||
procedure TQtWidgetSet.OnWakeMainThread(Sender: TObject);
|
||||
var
|
||||
Event: QEventH;
|
||||
|
||||
@ -126,7 +126,6 @@ type
|
||||
procedure SlotShow(vShow: Boolean); cdecl;
|
||||
function SlotClose: Boolean; cdecl; virtual;
|
||||
procedure SlotDestroy; cdecl;
|
||||
procedure SlotFocus(Event: QEventH; FocusIn: Boolean); cdecl;
|
||||
procedure SlotHover(Sender: QObjectH; Event: QEventH); cdecl;
|
||||
function SlotKey(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
|
||||
procedure SlotMouse(Sender: QObjectH; Event: QEventH); cdecl;
|
||||
@ -1518,14 +1517,6 @@ begin
|
||||
QEventDestroy: SlotDestroy;
|
||||
QEventEnter,
|
||||
QEventLeave: SlotMouseEnter(Sender, Event);
|
||||
QEventFocusIn: SlotFocus(Event, True);
|
||||
QEventFocusOut:
|
||||
begin
|
||||
SlotFocus(Event, False);
|
||||
if QFocusEvent_reason(QFocusEventH(Event)) <> QtMouseFocusReason then
|
||||
releaseMouse;
|
||||
end;
|
||||
|
||||
QEventHoverEnter,
|
||||
QEventHoverLeave,
|
||||
QEventHoverMove:
|
||||
@ -1647,51 +1638,6 @@ begin
|
||||
DeliverMessage(Msg);
|
||||
end;
|
||||
|
||||
{------------------------------------------------------------------------------
|
||||
Function: TQtWidget.SlotFocus
|
||||
Params: None
|
||||
Returns: Nothing
|
||||
------------------------------------------------------------------------------}
|
||||
procedure TQtWidget.SlotFocus(Event: QEventH; FocusIn: Boolean); cdecl;
|
||||
{$ifdef VerboseFocus}
|
||||
const
|
||||
QtFocusReasonToStr: array[QtFocusReason] of String =
|
||||
(
|
||||
{QtMouseFocusReason } 'QtMouseFocusReason',
|
||||
{QtTabFocusReason } 'QtTabFocusReason',
|
||||
{QtBacktabFocusReason } 'QtBacktabFocusReason',
|
||||
{QtActiveWindowFocusReason} 'QtActiveWindowFocusReason',
|
||||
{QtPopupFocusReason } 'QtPopupFocusReason',
|
||||
{QtShortcutFocusReason } 'QtShortcutFocusReason',
|
||||
{QtMenuBarFocusReason } 'QtMenuBarFocusReason',
|
||||
{QtOtherFocusReason } 'QtOtherFocusReason',
|
||||
{QtNoFocusReason } 'QtNoFocusReason'
|
||||
);
|
||||
{$endif}
|
||||
var
|
||||
Msg: TLMessage;
|
||||
begin
|
||||
{$ifdef VerboseFocus}
|
||||
WriteLn('TQtWidget.SlotFocus In=',FocusIn,' For ', dbgsname(LCLObject),
|
||||
' Reason = ', QtFocusReasonToStr[QFocusEvent_reason(QFocusEventH(Event))]);
|
||||
if QFocusEvent_reason(QFocusEventH(Event)) = QtTabFocusReason then
|
||||
DebugLn('Warning Qt handled Tab and set focus iself. Event for object ', dbgsname(LCLObject));
|
||||
{$endif}
|
||||
|
||||
FillChar(Msg, SizeOf(Msg), #0);
|
||||
|
||||
if FocusIn then
|
||||
Msg.Msg := LM_SETFOCUS
|
||||
else
|
||||
Msg.Msg := LM_KILLFOCUS;
|
||||
|
||||
DeliverMessage(Msg);
|
||||
|
||||
{$ifdef VerboseFocus}
|
||||
WriteLn('TQtWidget.SlotFocus END');
|
||||
{$endif}
|
||||
end;
|
||||
|
||||
procedure TQtWidget.SlotHover(Sender: QObjectH; Event: QEventH); cdecl;
|
||||
var
|
||||
Msg: TLMessage;
|
||||
|
||||
@ -1754,15 +1754,7 @@ begin
|
||||
begin
|
||||
// Capture widget can be child of complex control. In any case we should return TQtWidget as result.
|
||||
// So we will look for parent while not found apropriate LCL handle.
|
||||
repeat
|
||||
Widget := QtObjectFromWidgetH(w);
|
||||
if Widget = nil then
|
||||
begin
|
||||
w := QWidget_parentWidget(w);
|
||||
if w = nil then
|
||||
break;
|
||||
end;
|
||||
until Widget <> nil;
|
||||
Widget := GetFirstQtObjectFromWidgetH(w);
|
||||
Result := HWND(Widget);
|
||||
end
|
||||
else
|
||||
|
||||
Loading…
Reference in New Issue
Block a user