Qt: now we have accurate window dimensions under x11 - we use dummy widget approach. issue #36897

git-svn-id: trunk@62971 -
This commit is contained in:
zeljko 2020-04-14 12:51:45 +00:00
parent 93a6164805
commit f72d3068cc
6 changed files with 88 additions and 7 deletions

View File

@ -1187,6 +1187,7 @@ const
QtWA_WState_WindowOpacitySet = 119 { $77 };
QtWA_TranslucentBackground = 120 { $78 };
QtWA_AttributeCount = 121 { $79 };
QtWA_X11DoNotAcceptFocus = 132;
type
QtKey = cardinal; // Qt::Key (4)

View File

@ -44,6 +44,9 @@ uses
LMessages, LCLMessageGlue, LCLStrConsts,
Controls, ExtCtrls, Forms, StdCtrls, GraphType, GraphUtil, Themes,
// WS
{$IFDEF HASX11}
qtx11dummywidget,
{$ENDIF}
qtproc;
type
@ -128,6 +131,9 @@ type
FStockWhitePen: HPEN;
FStockSystemFont: HFONT;
FStockDefaultDC: HDC;
{$IFDEF HASX11}
FWSFrameRect: TRect;
{$ENDIF}
function CreateThemeServices: TThemeServices; override;
function EventFilter(Sender: QObjectH; Event: QEventH): Boolean; cdecl;
@ -151,6 +157,10 @@ type
procedure AppSetTitle(const ATitle: string); override;
function AppRemoveStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; override;
function AppRestoreStayOnTopFlags(const ASystemTopAlso: Boolean = False): Boolean; override;
{$IFDEF HASX11}
function CreateDummyWidgetFrame(const ALeft, ATop, AWidth, AHeight: integer): boolean;
function GetDummyWidgetFrame: TRect;
{$ENDIF}
public
constructor Create; override;
destructor Destroy; override;

View File

@ -114,6 +114,8 @@ begin
if (FWindowManagerName = 'marco') or (FWindowManagerName = 'gnome shell') or
(UTF8Pos('mutter', FWindowManagerName) > 0) then
FWindowManagerName := 'metacity';
if not FIsLibraryInstance then
FWSFrameRect := Rect(0, 0, 0, 0);
{$ENDIF}
{$IFDEF DARWIN}
// do not swap meta and ctrl keys, issue #20897
@ -539,6 +541,26 @@ begin
QtRestoreStayOnTop(ASystemTopAlso);
end;
{$IFDEF HASX11}
function TQtWidgetSet.CreateDummyWidgetFrame(const ALeft, ATop, AWidth,
AHeight: integer): boolean;
var
ADummy: TDummyWidget;
begin
Result := False;
ADummy := TDummyWidget.Create;
ADummy.ShowDummyWidget(ALeft, ATop, AWidth, AHeight);
FWSFrameRect := ADummy.GetWidgetFrame;
ADummy.Free;
Result := not IsRectEmpty(FWSFrameRect);
end;
function TQtWidgetSet.GetDummyWidgetFrame: TRect;
begin
Result := FWSFrameRect;
end;
{$ENDIF}
procedure TQtWidgetSet.SetOverrideCursor(const AValue: TObject);
begin
if AValue = nil then

View File

@ -636,6 +636,7 @@ type
TQtMainWindow = class(TQtWidget)
private
FBlocked: Boolean;
FFirstPaintEvent: boolean;
FIsFrameWindow: Boolean;
LayoutWidget: QBoxLayoutH;
FCWEventHook: QObject_hookH;
@ -703,6 +704,7 @@ type
procedure setRealPopupParent(NewParent: QWidgetH);
property Blocked: Boolean read FBlocked write FBlocked;
property IsFrameWindow: Boolean read FIsFrameWindow write FIsFrameWindow; {check if our LCLObject is TCustomFrame}
property FirstPaintEvent: boolean read FFirstPaintEvent write FFirstPaintEvent; {only for x11 - if firstpaintevent arrived we are 100% sure that frame is 100% accurate}
property ShowOnTaskBar: Boolean read FShowOnTaskBar;
public
function WinIDNeeded: boolean; override;
@ -6980,6 +6982,7 @@ begin
FFormHasInvalidPosition := False;
{$ENDIF}
FFirstPaintEvent := False;
FBlocked := False;
FShowOnTaskBar := False;
QtFormBorderStyle := Ord(bsSizeable);
@ -7058,6 +7061,8 @@ begin
if TQtMainWindow(Application.MainForm.Handle).MDIAreaHandle = nil then
raise Exception.Create('MDIChild can be added to MDIForm only !');
FFirstPaintEvent := True;
Result := QMdiSubWindow_create(nil, QtWindow);
// QMdiSubWindow already have an layout
@ -7069,8 +7074,10 @@ begin
begin
if not IsFrameWindow and (TCustomForm(LCLObject).FormStyle = fsSplash) and
not (csDesigning in LCLObject.ComponentState) then
Result := QWidget_create(nil, QtSplashScreen)
else
begin
FFirstPaintEvent := True;
Result := QWidget_create(nil, QtSplashScreen);
end else
Result := QWidget_create(nil, QtWindow);
QWidget_setAttribute(Result, QtWA_Hover);
@ -7578,6 +7585,11 @@ begin
' Event=', EventTypeToStr(Event),' inUpdate=',inUpdate);
{$endif}
{$IFDEF HASX11}
if (QEvent_type(Event) = QEventPaint) and not FFirstPaintEvent then
FFirstPaintEvent := True;
{$ENDIF}
{$IFDEF QTSCROLLABLEFORMS}
if Assigned(ScrollArea) and not IsMDIChild then
begin
@ -18426,6 +18438,7 @@ function TQtHintWindow.CreateWidget(const AParams: TCreateParams): QWidgetH;
var
Parent: QWidgetH;
begin
FFirstPaintEvent := True;
FHasPaint := True;
FNeedRestoreVisible := False;
if AParams.WndParent <> 0 then

View File

@ -4530,7 +4530,8 @@ end;
function TQtWidgetSet.GetWindowRect(Handle: hwnd; var ARect: TRect): Integer;
var
APos: TQtPoint;
R: TRect;
R, AFrame: TRect;
AForm: TCustomForm;
begin
{$ifdef VerboseQtWinAPI}
WriteLn('[WinAPI GetWindowRect]');
@ -4547,6 +4548,27 @@ begin
exit(-1);
end;
{$ENDIF}
{$IFDEF HASX11}
if (TQtWidget(Handle) is TQtMainWindow) and Assigned(TQtWidget(Handle).LCLObject) and
(TQtWidget(Handle).LCLObject.Parent = nil) and
not TQtMainWindow(Handle).FirstPaintEvent and not IsRectEmpty(QtWidgetSet.GetDummyWidgetFrame) then
begin
AForm := TCustomForm(TQtWidget(Handle).LCLObject);
if not (AForm.FormStyle in [fsMDIChild, fsSplash]) and (AForm.BorderStyle <> bsNone) and
not IsFormDesign(AForm) then
begin
R := AForm.BoundsRect;
AFrame := QtWidgetSet.GetDummyWidgetFrame;
// apply frame size to lcl form.
R.Right += AFrame.Left + AFrame.Right;
R.Bottom += AFrame.Top + AFrame.Bottom;
ARect := R; //this is now real size under x11 even on unmapped window :)
exit(-1);
end;
end;
{$ENDIF}
APos := QtPoint(0,0);
QWidget_mapToGlobal(TQtWidget(Handle).Widget, @APos, @APos);

View File

@ -187,6 +187,9 @@ var
Str: WideString;
APopupParent: TCustomForm;
AForm: TCustomForm;
{$IFDEF HASX11}
AWindowManager: String;
{$ENDIF}
begin
{$ifdef VerboseQt}
WriteLn('[TQtWSCustomForm.CreateHandle] Height: ', IntToStr(AWinControl.Height),
@ -245,6 +248,19 @@ begin
QtMainWindow.FrameMargins := QtWidgetSet.WSFrameMargins;
{$ENDIF}
{$IFDEF HASX11}
if QtMainWindow.IsMainForm and not Application.HasOption('disableaccurateframe') then
begin
AWindowManager := LowerCase(GetWindowManager);
//Kwin,Openbox,wmaker-common - ok
if Application.HasOption('hideaccurateframe') or not
( (AWindowManager = 'kwin') or (AWindowManager = 'openbox') or (AWindowManager = 'wmaker-common') ) then
QtWidgetSet.CreateDummyWidgetFrame(AWinControl.Left, AWinControl.Top, AWinControl.Width, AWinControl.Height)
else
QtWidgetSet.CreateDummyWidgetFrame(-1, -1, -1, -1); {only mentioned window managers literally move dummy widget out of screen - no flickering}
end;
{$ENDIF}
// Sets Various Events
QtMainWindow.AttachEvents;
{$IFDEF QTSCROLLABLEFORMS}
@ -612,9 +628,6 @@ begin
Widget.EndUpdate;
{$IFDEF HASX11}
if AWinControl.HandleObjectShouldBeVisible then
QCoreApplication_processEvents(QEventLoopAllEvents);
if (Application.TaskBarBehavior = tbSingleButton) or
(ACustomForm.ShowInTaskBar <> stDefault) then
SetShowInTaskbar(ACustomForm, ACustomForm.ShowInTaskBar);
@ -636,7 +649,7 @@ begin
end else
if (ACustomForm.FormStyle = fsSplash) then
begin
QWidget_repaint(Widget.GetContainerWidget);
QWidget_update(Widget.GetContainerWidget);
QCoreApplication_processEvents(QEventLoopExcludeUserInputEvents);
end;
end;