mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-12 22:40:15 +02:00
Qt: added qtx11dummywidget unit, will be used to get accurate frame - eg GetWindowRect() before widget is mapped. part of issue #36897
git-svn-id: trunk@62969 -
This commit is contained in:
parent
73b09c0bbb
commit
63be2586d7
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -10264,6 +10264,7 @@ lcl/interfaces/qt/qtwspairsplitter.pp svneol=native#text/pascal
|
|||||||
lcl/interfaces/qt/qtwsspin.pp svneol=native#text/pascal
|
lcl/interfaces/qt/qtwsspin.pp svneol=native#text/pascal
|
||||||
lcl/interfaces/qt/qtwsstdctrls.pp svneol=native#text/pascal
|
lcl/interfaces/qt/qtwsstdctrls.pp svneol=native#text/pascal
|
||||||
lcl/interfaces/qt/qtx11.inc svneol=native#text/plain
|
lcl/interfaces/qt/qtx11.inc svneol=native#text/plain
|
||||||
|
lcl/interfaces/qt/qtx11dummywidget.pas svneol=native#text/plain
|
||||||
lcl/interfaces/qt5/Makefile svneol=native#text/plain
|
lcl/interfaces/qt5/Makefile svneol=native#text/plain
|
||||||
lcl/interfaces/qt5/Makefile.compiled svneol=native#text/plain
|
lcl/interfaces/qt5/Makefile.compiled svneol=native#text/plain
|
||||||
lcl/interfaces/qt5/Makefile.fpc svneol=native#text/plain
|
lcl/interfaces/qt5/Makefile.fpc svneol=native#text/plain
|
||||||
|
167
lcl/interfaces/qt/qtx11dummywidget.pas
Normal file
167
lcl/interfaces/qt/qtx11dummywidget.pas
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
unit qtx11dummywidget;
|
||||||
|
|
||||||
|
{$mode objfpc}{$H+}
|
||||||
|
|
||||||
|
{we use this unit only under x11 to get accurate frame size in our aps}
|
||||||
|
|
||||||
|
interface
|
||||||
|
|
||||||
|
uses
|
||||||
|
Classes, SysUtils, Types, qtobjects, qt4;
|
||||||
|
|
||||||
|
type
|
||||||
|
|
||||||
|
{ TDummyWidget }
|
||||||
|
|
||||||
|
TDummyWidget = class(TQtObject)
|
||||||
|
private
|
||||||
|
FFrameRect: TRect;
|
||||||
|
FFirstPaintEvent: boolean;
|
||||||
|
function GetWidget: QWidgetH;
|
||||||
|
procedure SetWidget(AValue: QWidgetH);
|
||||||
|
public
|
||||||
|
constructor Create; override; overload;
|
||||||
|
function GetWidgetFrame: TRect;
|
||||||
|
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl; override;
|
||||||
|
function ShowDummyWidget(const ALeft, ATop, AWidth,
|
||||||
|
AHeight: integer): boolean;
|
||||||
|
procedure SendToBack;
|
||||||
|
procedure HideWidget;
|
||||||
|
property Widget: QWidgetH read GetWidget write SetWidget;
|
||||||
|
end;
|
||||||
|
|
||||||
|
implementation
|
||||||
|
uses LCLProc, qtint;
|
||||||
|
|
||||||
|
{ TDummyWidget }
|
||||||
|
|
||||||
|
function TDummyWidget.GetWidget: QWidgetH;
|
||||||
|
begin
|
||||||
|
Result := QWidgetH(TheObject);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDummyWidget.SetWidget(AValue: QWidgetH);
|
||||||
|
begin
|
||||||
|
TheObject := AValue;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$DEFINE DEBUGQTFRAMESIZE}
|
||||||
|
function TDummyWidget.ShowDummyWidget(const ALeft, ATop, AWidth,
|
||||||
|
AHeight: integer): boolean;
|
||||||
|
var
|
||||||
|
R: TRect;
|
||||||
|
{$IFDEF DEBUGQTFRAMESIZE}
|
||||||
|
ATicks: QWord;
|
||||||
|
{$ENDIF}
|
||||||
|
ALoop: integer;
|
||||||
|
AMaxLoops: integer;
|
||||||
|
begin
|
||||||
|
Result := Assigned(Widget);
|
||||||
|
if Result then
|
||||||
|
begin
|
||||||
|
if not IsWayland and QX11Info_isCompositingManagerRunning then
|
||||||
|
{it is possible that we need 50-100 msec to get frame when running under compositing manager.
|
||||||
|
Measured composition managers: kwin 89 msec}
|
||||||
|
AMaxLoops := 200000
|
||||||
|
else
|
||||||
|
AMaxLoops := 20000;
|
||||||
|
{$IFDEF DEBUGQTFRAMESIZE}
|
||||||
|
writeln('ShowDummyWidget(start) WindowManager="',GetWindowManager,'" Compositing enabled="',QX11Info_isCompositingManagerRunning,'" IsWayland="',IsWayland,'" MaxLoops=',AMaxLoops);
|
||||||
|
ATicks := GetTickCount64;
|
||||||
|
{$ENDIF}
|
||||||
|
if (ALeft <= 0) and (ATop <= 0) and (AWidth <= 0) and (AHeight <= 0) then
|
||||||
|
begin
|
||||||
|
//move off visible screen, some wm's does not allow such construct.
|
||||||
|
QWidget_move(Widget, -200, 0);
|
||||||
|
//set some reasonable size
|
||||||
|
QWidget_resize(Widget, 100, 75);
|
||||||
|
end else
|
||||||
|
begin
|
||||||
|
QWidget_move(Widget, ALeft + 1, ATop + 1);
|
||||||
|
QWidget_resize(Widget, AWidth - 1, AHeight - 1);
|
||||||
|
end;
|
||||||
|
QWidget_setAttribute(Widget, QtWA_X11DoNotAcceptFocus, True);
|
||||||
|
QWidget_show(Widget);
|
||||||
|
|
||||||
|
{We are waiting until dummy window is laid out on screen by window manager
|
||||||
|
ALoop variable is needed to avoid infinite loop.
|
||||||
|
Usually we get result in about 20-30msec on modern X11 without compositing,
|
||||||
|
but 30-100 msec on wm with compositing enabled.
|
||||||
|
Older X11 or slower machine might need more loops to get result,
|
||||||
|
but it won't be over 200 msec in any case.}
|
||||||
|
|
||||||
|
ALoop := 0; // avoid infinite loop
|
||||||
|
while not FFirstPaintEvent do
|
||||||
|
begin
|
||||||
|
inc(ALoop);
|
||||||
|
QCoreApplication_processEvents();
|
||||||
|
if ALoop > AMaxLoops then
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
{$IFDEF DEBUGQTFRAMESIZE}
|
||||||
|
writeln('ShowDummyWidget: 1st LOOP=',ALoop);
|
||||||
|
{$ENDIF}
|
||||||
|
R := Rect(0 ,0, 0, 0);
|
||||||
|
ALoop := 0; // avoid infinite loop
|
||||||
|
//Qt4 sets QtWA_Mapped before first paint event and that's wrong since x11 did not update decoration yet.
|
||||||
|
//so we MUST wait infinite for the first paint event.
|
||||||
|
while (R.Top <= 0) do // qt4 sets QtWA_Mapped before first paint event :(, maybe we should add eventFilter to this widget and wait for paint event
|
||||||
|
begin
|
||||||
|
inc(ALoop);
|
||||||
|
R := GetWidgetFrame;
|
||||||
|
QCoreApplication_processEvents();
|
||||||
|
if ALoop > AMaxLoops then
|
||||||
|
break;
|
||||||
|
end;
|
||||||
|
|
||||||
|
{$IFDEF DEBUGQTFRAMESIZE}
|
||||||
|
writeln('ShowDummyWidget: 2nd LOOP=',ALoop,' LAST R=',dbgs(R));
|
||||||
|
writeln('ShowDummyWidget: *finished* FRAME=',dbgs(GetWidgetFrame),' in ',GetTickCount64 - ATicks,' msec ');
|
||||||
|
{$ENDIF}
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
|
||||||
|
constructor TDummyWidget.Create;
|
||||||
|
begin
|
||||||
|
inherited Create;
|
||||||
|
FFrameRect := Rect(0, 0, 0, 0);
|
||||||
|
Widget := QWidget_create(nil, QtWindow);
|
||||||
|
QWidget_setAttribute(Widget, QtWA_ShowWithoutActivating);
|
||||||
|
QWidget_setFocusPolicy(Widget, QtNoFocus);
|
||||||
|
AttachEvents;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDummyWidget.GetWidgetFrame: TRect;
|
||||||
|
var
|
||||||
|
AFrame, AGeometry: TRect;
|
||||||
|
begin
|
||||||
|
Result := FFrameRect;
|
||||||
|
if not Assigned(Widget) then
|
||||||
|
exit;
|
||||||
|
QWidget_frameGeometry(Widget, @AFrame);
|
||||||
|
QWidget_geometry(Widget, @AGeometry);
|
||||||
|
FFrameRect := Rect(AGeometry.Left - AFrame.Left, AGeometry.Top - AFrame.Top, AFrame.Right - AGeometry.Right, AFrame.Bottom - AGeometry.Bottom);
|
||||||
|
Result := FFrameRect;
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TDummyWidget.EventFilter(Sender: QObjectH; Event: QEventH): Boolean;
|
||||||
|
cdecl;
|
||||||
|
begin
|
||||||
|
Result := False;
|
||||||
|
if not FFirstPaintEvent and (QEvent_type(Event) = QEventPaint) then
|
||||||
|
FFirstPaintEvent := True;
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDummyWidget.SendToBack;
|
||||||
|
begin
|
||||||
|
if Assigned(Widget) then
|
||||||
|
QWidget_lower(Widget);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure TDummyWidget.HideWidget;
|
||||||
|
begin
|
||||||
|
if Assigned(Widget) then
|
||||||
|
QWidget_hide(Widget);
|
||||||
|
end;
|
||||||
|
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user