mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-11 16:36:01 +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/qtwsstdctrls.pp svneol=native#text/pascal
|
||||
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.compiled 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