1{ $Id: qtwsforms.pp 60289 2019-02-02 18:44:59Z mattias $}
2{
3 *****************************************************************************
4 *                               QtWSForms.pp                                *
5 *                               ------------                                *
6 *                                                                           *
7 *                                                                           *
8 *****************************************************************************
9
10 *****************************************************************************
11  This file is part of the Lazarus Component Library (LCL)
12
13  See the file COPYING.modifiedLGPL.txt, included in this distribution,
14  for details about the license.
15 *****************************************************************************
16}
17unit QtWSForms;
18
19{$mode objfpc}{$H+}
20
21interface
22
23{$I qtdefines.inc}
24
25uses
26  // Bindings
27  qt4,
28  qtobjects, qtwidgets, qtproc,
29  // LCL
30  SysUtils, Classes, types, Controls, LCLType, Forms,
31  // Widgetset
32  InterfaceBase, WSForms, WSProc, WSLCLClasses;
33
34type
35
36  { TQtWSScrollingWinControl }
37
38  TQtWSScrollingWinControl = class(TWSScrollingWinControl)
39  published
40  end;
41
42  { TQtWSScrollBox }
43
44  TQtWSScrollBox = class(TWSScrollBox)
45  published
46  end;
47
48  { TQtWSCustomFrame }
49
50  TQtWSCustomFrame = class(TWSCustomFrame)
51  published
52    class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
53    class procedure ScrollBy(const AWinControl: TWinControl; DeltaX, DeltaY: integer); override;
54  end;
55
56  { TQtWSFrame }
57
58  TQtWSFrame = class(TWSFrame)
59  published
60  end;
61
62  { TQtWSCustomForm }
63
64  TQtWSCustomForm = class(TWSCustomForm)
65  private
66    class function GetQtBorderStyle(const AFormBorderStyle: TFormBorderStyle): QtWindowFlags;
67    class function GetQtBorderIcons(const AFormBorderStyle: TFormBorderStyle; ABorderIcons: TBorderIcons): QtWindowFlags;
68    class function GetQtFormStyle(const AFormStyle: TFormStyle): QtWindowFlags;
69    class procedure UpdateWindowFlags(const AWidget: TQtMainWindow;
70      ABorderStyle: TFormBorderStyle; ABorderIcons: TBorderIcons; AFormStyle: TFormStyle);
71  published
72    class function GetDefaultClientRect(const AWinControl: TWinControl;
73             const {%H-}aLeft, {%H-}aTop, aWidth, aHeight: integer; var aClientRect: TRect
74             ): boolean; override;
75    class function  CanFocus(const AWinControl: TWinControl): Boolean; override;
76    class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
77
78    class procedure CloseModal(const ACustomForm: TCustomForm); override;
79    class procedure DestroyHandle(const AWinControl: TWinControl); override;
80    class procedure ScrollBy(const AWinControl: TWinControl; DeltaX, DeltaY: integer); override;
81    class procedure SetAllowDropFiles(const AForm: TCustomForm; AValue: Boolean); override;
82    class procedure SetFormBorderStyle(const AForm: TCustomForm; const AFormBorderStyle: TFormBorderStyle); override;
83    class procedure SetFormStyle(const AForm: TCustomform; const AFormStyle, AOldFormStyle: TFormStyle); override;
84    class procedure SetIcon(const AForm: TCustomForm; const Small, Big: HICON); override;
85    class procedure SetRealPopupParent(const ACustomForm: TCustomForm;
86       const APopupParent: TCustomForm); override;
87    class procedure SetShowInTaskbar(const AForm: TCustomForm; const AValue: TShowInTaskbar); override;
88    class procedure ShowHide(const AWinControl: TWinControl); override; //TODO: rename to SetVisible(control, visible)
89    class procedure ShowModal(const ACustomForm: TCustomForm); override;
90    class procedure SetBorderIcons(const AForm: TCustomForm; const ABorderIcons: TBorderIcons); override;
91    class procedure SetAlphaBlend(const ACustomForm: TCustomForm;
92       const AlphaBlend: Boolean; const Alpha: Byte); override;
93
94    { mdi support }
95    class function ActiveMDIChild(const AForm: TCustomForm): TCustomForm; override;
96    class function Cascade(const AForm: TCustomForm): Boolean; override;
97    class function GetClientHandle(const AForm: TCustomForm): HWND; override;
98    class function GetMDIChildren(const AForm: TCustomForm; AIndex: Integer): TCustomForm; override;
99    class function Next(const AForm: TCustomForm): Boolean; override;
100    class function Previous(const AForm: TCustomForm): Boolean; override;
101    class function Tile(const AForm: TCustomForm): Boolean; override;
102    class function MDIChildCount(const AForm: TCustomForm): Integer; override;
103
104  end;
105
106  { TQtWSForm }
107
108  TQtWSForm = class(TWSForm)
109  published
110  end;
111
112  { TQtWSHintWindow }
113
114  TQtWSHintWindow = class(TWSHintWindow)
115  published
116    class function CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle; override;
117    class procedure ShowHide(const AWinControl: TWinControl); override;
118  end;
119
120  { TQtWSScreen }
121
122  TQtWSScreen = class(TWSScreen)
123  published
124  end;
125
126  { TQtWSApplicationProperties }
127
128  TQtWSApplicationProperties = class(TWSApplicationProperties)
129  published
130  end;
131
132
133implementation
134
135uses qtint, LCLIntf
136  {$IF DEFINED(VerboseQtResize) OR DEFINED(DEBUGQTUSEACCURATEFRAME)}, LCLProc{$ENDIF}
137  ;
138
139{ TQtWSCustomFrame }
140
141class function TQtWSCustomFrame.CreateHandle(const AWinControl: TWinControl;
142  const AParams: TCreateParams): TLCLIntfHandle;
143var
144  QtFrame: TQtMainWindow;
145begin
146  if IsFormDesign(AWinControl) or (csDesigning in AWinControl.ComponentState) then
147    QtFrame := TQtDesignWidget.Create(AWinControl, AParams)
148  else
149    QtFrame := TQtMainWindow.Create(AWinControl, AParams);
150  QtFrame.setWindowFlags(QtWindow or QtFramelessWindowHint);
151  QtFrame.AttachEvents;
152  {$IFDEF QTSCROLLABLEFORMS}
153  if Assigned(QtFrame.ScrollArea) then
154    QtFrame.ScrollArea.AttachEvents;
155  {$ENDIF}
156  QtFrame.MenuBar.AttachEvents;
157  Result := TLCLIntfHandle(QtFrame);
158end;
159
160class procedure TQtWSCustomFrame.ScrollBy(const AWinControl: TWinControl;
161  DeltaX, DeltaY: integer);
162{$IFDEF QTSCROLLABLEFORMS}
163var
164  Widget: TQtMainWindow;
165{$ENDIF}
166begin
167  {$IFDEF QTSCROLLABLEFORMS}
168  if not WSCheckHandleAllocated(AWinControl, 'ScrollBy') then
169    Exit;
170  Widget := TQtMainWindow(AWinControl.Handle);
171  if Assigned(Widget.ScrollArea) then
172    Widget.ScrollArea.scroll(DeltaX, DeltaY);
173  {$ENDIF}
174end;
175
176{------------------------------------------------------------------------------
177  Method: TQtWSCustomForm.CreateHandle
178  Params:  None
179  Returns: Nothing
180
181  Creates a Qt Form and initializes it according to it's properties
182 ------------------------------------------------------------------------------}
183class function TQtWSCustomForm.CreateHandle(const AWinControl: TWinControl;
184  const AParams: TCreateParams): TLCLIntfHandle;
185var
186  QtMainWindow: TQtMainWindow;
187  Str: WideString;
188  APopupParent: TCustomForm;
189  AForm: TCustomForm;
190begin
191  {$ifdef VerboseQt}
192    WriteLn('[TQtWSCustomForm.CreateHandle] Height: ', IntToStr(AWinControl.Height),
193     ' Width: ', IntToStr(AWinControl.Width));
194  {$endif}
195
196  // Creates the window
197  {$IFDEF HASX11}
198  if (QtVersionMajor = 4) and (QtVersionMinor >= 6) then
199    QCoreApplication_setAttribute(QtAA_ImmediateWidgetCreation, True);
200  {$ENDIF}
201  if IsFormDesign(AWinControl) or (csDesigning in AWinControl.ComponentState) then
202    QtMainWindow := TQtDesignWidget.Create(AWinControl, AParams)
203  else
204    QtMainWindow := TQtMainWindow.Create(AWinControl, AParams);
205
206  AForm := TCustomForm(AWinControl);
207
208  QtMainWindow.QtFormBorderStyle := Ord(AForm.BorderStyle);
209  QtMainWindow.QtFormStyle := Ord(AForm.FormStyle);
210
211  Str := AWinControl{%H-}.Caption;
212  QtMainWindow.SetWindowTitle(@Str);
213
214  if not (csDesigning in AForm.ComponentState) then
215  begin
216    UpdateWindowFlags(QtMainWindow, AForm.BorderStyle,
217      AForm.BorderIcons, AForm.FormStyle);
218  end;
219
220  if (not (AForm.FormStyle in [fsMDIChild]) or (csDesigning in AForm.ComponentState)) and
221     (Application <> nil) and
222     (Application.MainForm <> nil) and
223     (Application.MainForm.HandleAllocated) and
224     (Application.MainForm <> AForm) then
225  begin
226    if (AForm.ShowInTaskBar = stNever)
227       {$ifdef HASX11}
228       {QtTool have not minimize button !}
229       and (not (AForm.BorderStyle in [bsSizeToolWin, bsToolWindow]) and
230          not (csDesigning in AForm.ComponentState))
231       {$endif} then
232      QtMainWindow.setShowInTaskBar(False);
233    APopupParent := AForm.GetRealPopupParent;
234    if APopupParent<>nil then
235      QtMainWindow.setRealPopupParent(TQtWidget(APopupParent.Handle).Widget);
236  end;
237
238  {$IFDEF HASX11}
239  if (QtVersionMajor = 4) and (QtVersionMinor >= 6) then
240    QCoreApplication_setAttribute(QtAA_ImmediateWidgetCreation, False);
241  {$ENDIF}
242
243  {$IFDEF QtUseAccurateFrame}
244  if QtMainWindow.IsFramedWidget then
245    QtMainWindow.FrameMargins := QtWidgetSet.WSFrameMargins;
246  {$ENDIF}
247
248  // Sets Various Events
249  QtMainWindow.AttachEvents;
250  {$IFDEF QTSCROLLABLEFORMS}
251  if Assigned(QtMainWindow.ScrollArea) then
252    QtMainWindow.ScrollArea.AttachEvents;
253  {$ENDIF}
254  QtMainWindow.MenuBar.AttachEvents;
255
256  if not (csDesigning in AForm.ComponentState) and
257    (AForm.FormStyle in [fsMDIChild]) and
258    (Application.MainForm.FormStyle = fsMdiForm) then
259  begin
260    QMdiArea_addSubWindow(
261      QMdiAreaH(TQtMainWindow(Application.MainForm.Handle).MDIAreaHandle.Widget),
262      QtMainWindow.Widget, QtMainWindow.windowFlags);
263    QtMainWindow.MDIChildArea := TQtMainWindow(Application.MainForm.Handle).MDIAreaHandle;
264  end;
265
266  // Return the handle
267  Result := TLCLIntfHandle(QtMainWindow);
268end;
269
270{------------------------------------------------------------------------------
271  Method: TQtWSCustomForm.CloseModal
272  Params:
273  Returns: Nothing
274 ------------------------------------------------------------------------------}
275class procedure TQtWSCustomForm.CloseModal(const ACustomForm: TCustomForm);
276begin
277  inherited CloseModal(ACustomForm);
278end;
279
280class procedure TQtWSCustomForm.DestroyHandle(const AWinControl: TWinControl);
281var
282  w: TQtWidget;
283begin
284  w := TQtWidget(AWinControl.Handle);
285  {forms which have another widget as parent
286   eg.form inside tabpage or mdichilds
287   can segfault without hiding before release.
288   So we save our day here.}
289  if w.getVisible and (w.getParent <> nil) then
290    w.Hide;
291  w.Release;
292end;
293
294class procedure TQtWSCustomForm.ScrollBy(const AWinControl: TWinControl;
295  DeltaX, DeltaY: integer);
296{$IFDEF QTSCROLLABLEFORMS}
297var
298  Widget: TQtMainWindow;
299{$ENDIF}
300begin
301  {$IFDEF QTSCROLLABLEFORMS}
302  if not WSCheckHandleAllocated(AWinControl, 'ScrollBy') then
303    Exit;
304  Widget := TQtMainWindow(AWinControl.Handle);
305  if Assigned(Widget.ScrollArea) then
306    Widget.ScrollArea.scroll(DeltaX, DeltaY);
307  {$ENDIF}
308end;
309
310{------------------------------------------------------------------------------
311  Method: TQtWSCustomForm.SetAllowDropFiles
312  Params:
313  Returns: Nothing
314 ------------------------------------------------------------------------------}
315class procedure TQtWSCustomForm.SetAllowDropFiles(const AForm: TCustomForm;
316  AValue: Boolean);
317begin
318  if AForm.HandleAllocated then
319    TQtMainWindow(AForm.Handle).setAcceptDropFiles(AValue);
320end;
321
322{------------------------------------------------------------------------------
323  Method: TQtWSCustomForm.SetFormBorderStyle
324  Params:
325  Returns: Nothing
326 ------------------------------------------------------------------------------}
327class procedure TQtWSCustomForm.SetFormBorderStyle(const AForm: TCustomForm;
328  const AFormBorderStyle: TFormBorderStyle);
329var
330  QtWin: TQtMainWindow;
331begin
332  QtWin := TQtMainWindow(AForm.Handle);
333  if (AForm.Parent <> nil) and (QtWin.QtFormBorderStyle <> Ord(AFormBorderStyle)) then
334    RecreateWnd(AForm)
335  else
336  begin
337    QtWin.QtFormBorderStyle := Ord(AFormBorderStyle);
338    UpdateWindowFlags(QtWin, AFormBorderStyle,
339      AForm.BorderIcons, AForm.FormStyle);
340  end;
341end;
342
343class procedure TQtWSCustomForm.SetFormStyle(const AForm: TCustomform;
344  const AFormStyle, AOldFormStyle: TFormStyle);
345var
346  QtWin: TQtMainWindow;
347begin
348  QtWin := TQtMainWindow(AForm.Handle);
349  if (AForm.Parent <> nil) and (QtWin.QtFormStyle <> Ord(AFormStyle)) then
350    RecreateWnd(AForm)
351  else
352  begin
353    QtWin.QtFormStyle := Ord(AFormStyle);
354    UpdateWindowFlags(QtWin, AForm.BorderStyle, AForm.BorderIcons, AFormStyle);
355  end;
356end;
357
358{------------------------------------------------------------------------------
359  Method: TQtWSCustomForm.SetIcon
360  Params:
361  Returns: Nothing
362 ------------------------------------------------------------------------------}
363class procedure TQtWSCustomForm.SetIcon(const AForm: TCustomForm; const Small, Big: HICON);
364var
365  Icon: TQtIcon;
366begin
367  Icon := TQtIcon(Big);
368  if Icon <> nil then
369    TQtWidget(AForm.Handle).setWindowIcon(Icon.Handle)
370  else
371    TQtWidget(AForm.Handle).setWindowIcon(nil);
372end;
373
374class procedure TQtWSCustomForm.SetRealPopupParent(
375  const ACustomForm: TCustomForm; const APopupParent: TCustomForm);
376var
377  PopupParent: QWidgetH;
378begin
379  if not ACustomForm.HandleAllocated or (csDestroying in ACustomForm.ComponentState) then
380    exit;
381  if Assigned(APopupParent) then
382    PopupParent := TQtWidget(APopupParent.Handle).Widget
383  else
384    PopupParent := nil;
385  TQtMainWindow(ACustomForm.Handle).setRealPopupParent(PopupParent);
386end;
387
388{------------------------------------------------------------------------------
389  Method: TQtWSCustomForm.SetShowInTaskbar
390  Params:
391  Returns: Nothing
392 ------------------------------------------------------------------------------}
393class procedure TQtWSCustomForm.SetShowInTaskbar(const AForm: TCustomForm; const AValue: TShowInTaskbar);
394var
395  Enable: Boolean;
396begin
397  if (AForm.Parent<>nil) or not (AForm.HandleAllocated) then exit;
398
399  Enable := AValue <> stNever;
400  if (AValue = stDefault) and
401    {$IFDEF HASX11}
402    TQtMainWindow(AForm.Handle).ShowOnTaskBar and
403    {$ENDIF}
404     (Application<>nil) and
405     (Application.MainForm <> nil) and
406     (Application.MainForm <> AForm) then
407    Enable := false;
408  {$IFDEF HASX11}
409  if (AForm.FormStyle <> fsMDIChild) then
410    SetSkipX11Taskbar(TQtMainWindow(AForm.Handle).Widget, not Enable);
411  {$ENDIF}
412  TQtMainWindow(AForm.Handle).setShowInTaskBar(Enable);
413end;
414
415class procedure TQtWSCustomForm.ShowHide(const AWinControl: TWinControl);
416const
417  LCLToQtWindowState: array[TWindowState] of QtWindowState = (
418 { wsNormal    } QtWindowNoState,
419 { wsMinimized } QtWindowMinimized,
420 { wsMaximized } QtWindowMaximized,
421 { wsFullScreen} QtWindowFullScreen
422  );
423var
424  Widget: TQtMainWindow;
425  R: TRect;
426  {$IFDEF HASX11}
427  APopupParent: TCustomForm;
428  ActiveWin: HWND;
429  W: QWidgetH;
430  {$ENDIF}
431  Flags: Cardinal;
432  ACustomForm: TCustomForm;
433
434  function ShowNonModalOverModal: Boolean;
435  var
436    AForm: TCustomForm;
437    AWidget: QWidgetH;
438  begin
439    Result := False;
440    AForm := TCustomForm(AWinControl);
441    if AWinControl.HandleObjectShouldBeVisible and
442      not (fsModal in AForm.FormState) and
443      (AForm.FormStyle <> fsMDIChild) and
444      not (AForm.FormStyle in fsAllStayOnTop) and
445      (AForm.Parent = nil) and
446      (QApplication_activeModalWidget() <> nil) and
447      (AForm.BorderStyle in [bsDialog, bsSingle, bsSizeable]) and
448      (AForm.PopupParent = nil) and (AForm.PopupMode = pmNone) then
449    begin
450      AWidget := TQtWidget(AForm.Handle).Widget;
451      {$IFDEF DARWIN}
452      QWidget_setParent(AWidget, QApplication_activeWindow());
453      QWidget_setWindowFlags(Widget.Widget, QtSheet or
454        GetQtBorderIcons(TCustomForm(AWinControl).BorderStyle,
455          TCustomForm(AWinControl).BorderIcons));
456      {$ELSE}
457      QWidget_setParent(AWidget, QApplication_desktop());
458      {$IFDEF MSWINDOWS}
459      QWidget_setWindowFlags(Widget.Widget, QtDialog or
460        QtWindowSystemMenuHint or
461        GetQtBorderIcons(TCustomForm(AWinControl).BorderStyle,
462          TCustomForm(AWinControl).BorderIcons));
463      {$ENDIF}
464      QWidget_setWindowModality(AWidget, QtWindowModal);
465      {$ENDIF}
466      Result := True;
467    end;
468  end;
469
470begin
471  if not WSCheckHandleAllocated(AWinControl, 'ShowHide') then
472    Exit;
473
474  ACustomForm := TCustomForm(AWinControl);
475  Widget := TQtMainWindow(AWinControl.Handle);
476
477  {issue #34982}
478  if AWinControl.HandleObjectShouldBeVisible and Application.Terminated then
479    exit;
480
481  if AWinControl.HandleObjectShouldBeVisible then
482  begin
483    if fsModal in ACustomForm.FormState then
484    begin
485      {$ifdef MSWINDOWS}
486      // qt doesn't modal windows as QtTool.see issue #18709
487      if (ACustomForm.BorderStyle in [bsToolWindow, bsSizeToolWin]) then
488        QWidget_setWindowFlags(Widget.Widget, QtDialog);
489      if QApplication_activeModalWidget <> nil then
490        QWidget_setParent(Widget.Widget, QApplication_activeModalWidget);
491      {$endif}
492
493      {$ifdef HASX11}
494      if ((QtWidgetSet.WindowManagerName = 'kwin') and IsOldKDEInstallation) or
495        (QtWidgetSet.WindowManagerName = 'xfwm4') or
496        (QtWidgetSet.WindowManagerName = 'metacity') then
497      begin
498        W := nil;
499        ActiveWin := GetActiveWindow;
500        if ActiveWin <> 0 then
501        begin
502          if Assigned(TQtWidget(ActiveWin).LCLObject) then
503          begin
504            if (TQtWidget(ActiveWin).LCLObject is TCustomForm) then
505            begin
506              with TCustomForm(TQtWidget(ActiveWin).LCLObject) do
507              begin
508                if Visible and (FormStyle <> fsSplash) then
509                  W := TQtWidget(Handle).Widget;
510              end;
511            end;
512          end;
513        end;
514        if GetEnvironmentVariable('XDG_CURRENT_DESKTOP') = '' then
515          QWidget_setParent(Widget.Widget, W);
516      end else
517        QWidget_setParent(Widget.Widget, QApplication_desktop());
518      {$endif}
519
520      if ACustomForm.BorderStyle <> bsNone then
521      begin
522        QWidget_setWindowFlags(Widget.Widget, QtDialog or
523          {$ifdef darwin}
524          QtWindowSystemMenuHint or
525          {$endif}
526          GetQtBorderIcons(ACustomForm.BorderStyle,
527            ACustomForm.BorderIcons));
528      end;
529
530      Widget.setWindowModality(QtApplicationModal);
531    end;
532
533    if ACustomForm.FormStyle = fsMDIChild then
534    begin
535      {MDI windows have to be resized , since titlebar is included into widget geometry !}
536      if not (csDesigning in AWinControl.ComponentState)
537        and not Widget.isMaximized then
538      begin
539        QWidget_contentsRect(Widget.Widget, @R);
540        R.Right := ACustomForm.Width + R.Left;
541        R.Bottom := ACustomForm.Height + R.Top;
542        R.Left := Widget.MdiChildCount * 10;
543        R.Top := Widget.MdiChildCount * 10;
544        Widget.move(R.Left, R.Top);
545        Widget.resize(R.Right, R.Bottom);
546      end;
547    end;
548
549    if (ACustomForm.FormStyle <> fsMDIChild) or
550      (csDesigning in AWinControl.ComponentState) then
551    begin
552      if (csDesigning in AWinControl.ComponentState) and
553        (ACustomForm.WindowState = wsMaximized) then
554        Widget.setWindowState(LCLToQtWindowState[wsNormal])
555      else
556        Widget.setWindowState(LCLToQtWindowState[ACustomForm.WindowState]);
557    end;
558  end;
559
560  Widget.BeginUpdate;
561  if not (csDesigning in AWinControl.ComponentState) then
562  begin
563    if ShowNonModalOverModal then
564    // issue #12459
565    else
566    if AWinControl.HandleObjectShouldBeVisible
567      and (ACustomForm.FormStyle in fsAllStayOnTop) then
568    begin
569      Flags := Widget.windowFlags;
570      if (Flags and QtWindowStaysOnTopHint = 0) then
571      begin
572        Flags := Flags or QtWindowStaysOnTopHint;
573        Widget.setWindowFlags(Flags);
574      end;
575      if not Assigned(AWinControl.Parent) and
576        not (fsModal in ACustomForm.FormState) and
577        (ACustomForm.FormStyle <> fsMDIChild) and
578        (QApplication_activeModalWidget() <> nil) then
579          TQtMainWindow(Widget).setRealPopupParent(
580            QApplication_activeModalWidget());
581    end else
582    begin
583      if (ACustomForm.FormStyle in fsAllStayOnTop) then
584      begin
585        if not (csDestroying in AWinControl.ComponentState) then
586        begin
587          Flags := Widget.windowFlags;
588          Flags := Flags and not QtWindowStaysOnTopHint;
589          Widget.setWindowFlags(Flags);
590        end;
591      end;
592      {$IFDEF HASX11}
593      // issue #26018
594      if AWinControl.HandleObjectShouldBeVisible and
595        not (ACustomForm.FormStyle in fsAllStayOnTop) and
596        not (fsModal in ACustomForm.FormState) and
597        (ACustomForm.FormStyle <> fsMDIChild) then
598      begin
599        APopupParent := ACustomForm.GetRealPopupParent;
600        if (APopupParent <> nil) then
601        begin
602          Widget.setParent(TQtWidget(APopupParent.Handle).Widget);
603          {use direct X11 call instead of QtTool flag.issue #29253}
604          SetTransientForHint(Widget.Widget, TQtWidget(APopupParent.Handle).Widget);
605        end;
606      end;
607      {$ENDIF}
608    end;
609  end;
610
611  Widget.setVisible(AWinControl.HandleObjectShouldBeVisible);
612  Widget.EndUpdate;
613
614  {$IFDEF HASX11}
615  if AWinControl.HandleObjectShouldBeVisible then
616    QCoreApplication_processEvents(QEventLoopAllEvents);
617
618  if (Application.TaskBarBehavior = tbSingleButton) or
619    (ACustomForm.ShowInTaskBar <> stDefault) then
620      SetShowInTaskbar(ACustomForm, ACustomForm.ShowInTaskBar);
621
622  if AWinControl.HandleObjectShouldBeVisible and
623    not (csDesigning in ACustomForm.ComponentState) and
624        (ACustomForm.FormStyle <> fsMDIChild) then
625  begin
626    if (fsModal in ACustomForm.FormState) then
627    begin
628      if (Application.TaskBarBehavior <> tbSingleButton) then
629      begin
630        SetSkipX11Taskbar(Widget.Widget, True);
631        Widget.setShowInTaskBar(False);
632      end;
633      if (ACustomForm.BorderStyle <> bsNone) and
634        (QtWidgetSet.WindowManagerName = 'metacity') then
635          X11Raise(QWidget_winID(Widget.Widget));
636    end else
637    if (ACustomForm.FormStyle = fsSplash) then
638    begin
639      QWidget_repaint(Widget.GetContainerWidget);
640      QCoreApplication_processEvents(QEventLoopExcludeUserInputEvents);
641    end;
642  end;
643  {$ENDIF}
644end;
645
646{------------------------------------------------------------------------------
647  Method: TQtWSCustomForm.ShowModal
648  Params:
649  Returns: Nothing
650 ------------------------------------------------------------------------------}
651class procedure TQtWSCustomForm.ShowModal(const ACustomForm: TCustomForm);
652begin
653  {
654    Setting modal flags is done in TQtWSCustomControl.ShowHide
655    Since that flags has effect only when Widget is not visible
656
657    We can of course hide widget, set flags here and then show it, but we do not
658    want window flickering :)
659  }
660end;
661
662{------------------------------------------------------------------------------
663  Method: TQtWSCustomForm.SetBorderIcons
664  Params:
665  Returns: Nothing
666 ------------------------------------------------------------------------------}
667class procedure TQtWSCustomForm.SetBorderIcons(const AForm: TCustomForm;
668  const ABorderIcons: TBorderIcons);
669begin
670  UpdateWindowFlags(TQtMainWindow(AForm.Handle), AForm.BorderStyle, ABorderIcons, AForm.FormStyle);
671end;
672
673class procedure TQtWSCustomForm.SetAlphaBlend(const ACustomForm: TCustomForm;
674  const AlphaBlend: Boolean; const Alpha: Byte);
675begin
676  if AlphaBlend then
677    TQtMainWindow(ACustomForm.Handle).setWindowOpacity(Alpha / 255)
678  else
679    TQtMainWindow(ACustomForm.Handle).setWindowOpacity(1);
680end;
681
682class function TQtWSCustomForm.ActiveMDIChild(const AForm: TCustomForm
683  ): TCustomForm;
684var
685  MDIWorkSpace: QMdiAreaH;
686  ActiveChild: QWidgetH;
687  i: Integer;
688begin
689  Result := nil;
690  if not WSCheckHandleAllocated(AForm, 'ActiveMDIChild') then
691    Exit;
692  if not (AForm.FormStyle in [fsMDIForm, fsMDIChild]) then
693    exit;
694  if AForm.FormStyle = fsMDIForm then
695    MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget)
696  else
697    MDIWorkSpace := QMdiSubWindow_mdiArea(QMdiSubWindowH(TQtWidget(AForm.Handle).Widget));
698
699  if MDIWorkSpace <> nil then
700  begin
701    ActiveChild := QMdiArea_activeSubWindow(MDIWorkSpace);
702    for i := 0 to Screen.FormCount - 1 do
703    begin
704      if (Screen.Forms[i].HandleAllocated) and
705      (TQtWidget(Screen.Forms[i].Handle).Widget = ActiveChild) then
706      begin
707        Result := Screen.Forms[i];
708        break;
709      end;
710    end;
711  end;
712end;
713
714{------------------------------------------------------------------------------
715  Method: TQtWSCustomForm.Cascade
716  Params:  AForm fsMDIForm.
717  Returns: Nothing
718  Cascade mdi children.
719 ------------------------------------------------------------------------------}
720class function TQtWSCustomForm.Cascade(const AForm: TCustomForm): Boolean;
721var
722  MDIWorkspace: QMdiAreaH;
723begin
724  Result := False;
725  if not WSCheckHandleAllocated(AForm, 'Cascade') then
726    Exit;
727  if AForm.FormStyle <> fsMDIForm then
728    exit;
729  MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget);
730  QMdiArea_cascadeSubWindows(MDIWorkSpace);
731end;
732
733{------------------------------------------------------------------------------
734  Method: TQtWSCustomForm.Next
735  Params:  AForm fsMDIForm.
736  Returns: Nothing
737  Returns handle of mdi area container (viewport).
738  Currently not implemented.
739 ------------------------------------------------------------------------------}
740class function TQtWSCustomForm.GetClientHandle(const AForm: TCustomForm): HWND;
741begin
742  {TODO: make TQtMainWindow(AForm.Handle).MDIAreaHandle TQtWidget and return that,
743   but without attached events !}
744  Result := 0;
745  if not WSCheckHandleAllocated(AForm, 'GetClientHandle') then
746    Exit;
747  Result := HWND(TQtMainWindow(AForm.Handle).MDIAreaHandle);
748end;
749
750{------------------------------------------------------------------------------
751  Method: TQtWSCustomForm.Next
752  Params:  AForm: Parent fsMDIForm, AIndex - index of mdi child
753  Returns: Nothing
754  Returns MDI child window at index AIndex.
755 ------------------------------------------------------------------------------}
756class function TQtWSCustomForm.GetMDIChildren(const AForm: TCustomForm;
757  AIndex: Integer): TCustomForm;
758var
759  MDIWorkspace: QMdiAreaH;
760  IntAr: TPtrIntArray;
761  ChildAtIndex: QWidgetH;
762  i: Integer;
763begin
764  Result := nil;
765  if not WSCheckHandleAllocated(AForm, 'GetMDIChildren') then
766    Exit;
767  if not (AForm.FormStyle in [fsMDIForm, fsMDIChild]) then
768    exit;
769
770  if AForm.FormStyle = fsMDIForm then
771    MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget)
772  else
773    MDIWorkSpace := QMdiSubWindow_mdiArea(QMdiSubWindowH(TQtWidget(AForm.Handle).Widget));
774
775  if MDIWorkSpace <> nil then
776  begin
777    QMdiArea_subWindowList(MDIWorkSpace, @IntAr);
778    if (AIndex >= 0) and (AIndex <= High(IntAr)) then
779    begin
780      ChildAtIndex := QMdiSubWindowH(IntAr[AIndex]);
781      for i := 0 to Screen.FormCount - 1 do
782      begin
783        if TQtWidget(Screen.Forms[i].Handle).Widget = ChildAtIndex then
784        begin
785          Result := Screen.Forms[i];
786          break;
787        end;
788      end;
789    end;
790  end;
791end;
792
793{------------------------------------------------------------------------------
794  Method: TQtWSCustomForm.Next
795  Params:  AForm: Parent fsMDIForm
796  Returns: Nothing
797  Activates next MDI child window in chain, if next reaches last subwindow,
798  it restarts from first window.
799 ------------------------------------------------------------------------------}
800class function TQtWSCustomForm.Next(const AForm: TCustomForm): Boolean;
801var
802  MDIWorkspace: QMdiAreaH;
803begin
804  Result := False;
805  if not WSCheckHandleAllocated(AForm, 'Next') then
806    Exit;
807  if AForm.FormStyle <> fsMDIForm then
808    exit;
809  MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget);
810  QMdiArea_activateNextSubWindow(MDIWorkSpace);
811end;
812
813{------------------------------------------------------------------------------
814  Method: TQtWSCustomForm.Previous
815  Params:  AForm: Parent fsMDIForm
816  Returns: Nothing
817  Activates previous MDI child window in chain.
818 ------------------------------------------------------------------------------}
819class function TQtWSCustomForm.Previous(const AForm: TCustomForm): Boolean;
820var
821  MDIWorkspace: QMdiAreaH;
822begin
823  Result := False;
824  if not WSCheckHandleAllocated(AForm, 'Previous') then
825    Exit;
826  if AForm.FormStyle <> fsMDIForm then
827    exit;
828  MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget);
829  QMdiArea_activatePreviousSubWindow(MDIWorkSpace);
830end;
831
832{------------------------------------------------------------------------------
833  Method: TQtWSCustomForm.Tile
834  Params:  AForm: Parent fsMDIForm
835  Returns: Nothing
836  Tiles mdi children.
837 ------------------------------------------------------------------------------}
838class function TQtWSCustomForm.Tile(const AForm: TCustomForm): Boolean;
839var
840  MDIWorkspace: QMdiAreaH;
841begin
842  Result := False;
843  if not WSCheckHandleAllocated(AForm, 'Tile') then
844    Exit;
845  if AForm.FormStyle <> fsMDIForm then
846    exit;
847  MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget);
848  QMdiArea_tileSubWindows(MDIWorkSpace);
849end;
850
851{------------------------------------------------------------------------------
852  Method: TQtWSCustomForm.MDIChildCount
853  Params:  AForm: Parent fsMDIForm
854  Returns: Nothing
855  Returns number of mdi child windows.
856 ------------------------------------------------------------------------------}
857class function TQtWSCustomForm.MDIChildCount(const AForm: TCustomForm
858  ): Integer;
859var
860  MDIWorkspace: QMdiAreaH;
861  IntAr: TPtrIntArray;
862begin
863  Result := 0;
864  if not WSCheckHandleAllocated(AForm, 'MDIChildCount') then
865    Exit;
866  if not (AForm.FormStyle in [fsMDIForm, fsMDIChild]) then
867    exit;
868
869  if AForm.FormStyle = fsMDIForm then
870    MDIWorkSpace := QMdiAreaH(TQtMainWindow(AForm.Handle).MDIAreaHandle.Widget)
871  else
872    MDIWorkSpace := QMdiSubWindow_mdiArea(QMdiSubWindowH(TQtWidget(AForm.Handle).Widget));
873
874  if MDIWorkSpace <> nil then
875  begin
876    QMdiArea_subWindowList(MDIWorkSpace, @IntAr);
877    Result := length(IntAr);
878  end;
879end;
880
881{------------------------------------------------------------------------------
882  Method: TQtWSCustomForm.GetQtWindowBorderStyle
883  Params:  None
884  Returns: Nothing
885
886 ------------------------------------------------------------------------------}
887class function TQtWSCustomForm.GetQtBorderStyle(const AFormBorderStyle: TFormBorderStyle): QtWindowFlags;
888begin
889  case AFormBorderStyle of
890    bsNone:
891      Result := QtWindow or QtFramelessWindowHint;
892    bsSingle:
893      Result := QtWindow or QtMSWindowsFixedSizeDialogHint;
894    bsSizeable:
895      Result := QtWindow;
896    bsDialog:
897      Result := QtDialog or QtMSWindowsFixedSizeDialogHint;
898    bsToolWindow:
899      Result := QtTool or QtMSWindowsFixedSizeDialogHint;
900    bsSizeToolWin:
901      // qt on most platforms (except windows) doesn't have sizeToolWin, it's regular qtWindow
902      Result := {$ifdef windows}QtTool{$else}QtWindow{$endif};
903    else
904      Result := QtWidget;
905  end;
906end;
907
908{------------------------------------------------------------------------------
909  Method: TQtWSCustomForm.SetQtBorderIcons
910  Params:  None
911  Returns: Nothing
912
913  Same comment as SetQtWindowBorderStyle above
914 ------------------------------------------------------------------------------}
915class function TQtWSCustomForm.GetQtBorderIcons(const AFormBorderStyle: TFormBorderStyle; ABorderIcons: TBorderIcons): QtWindowFlags;
916begin
917  Result := 0;
918
919  case AFormBorderStyle of
920    bsNone: Exit;
921    bsDialog: ABorderIcons := ABorderIcons - [biMaximize, biMinimize];
922    bsToolWindow, bsSizeToolWin: ABorderIcons := ABorderIcons - [biMaximize, biMinimize, biHelp];
923  end;
924
925  Result := QtCustomizeWindowHint
926        or QtWindowTitleHint or QtWindowCloseButtonHint;
927
928  if (biSystemMenu in ABorderIcons) then
929    Result := Result or QtWindowSystemMenuHint;
930
931  if (biMinimize in ABorderIcons) then
932    Result := Result or QtWindowMinimizeButtonHint;
933
934  if (biMaximize in ABorderIcons) then
935    Result := Result or QtWindowMaximizeButtonHint;
936
937  if (biHelp in ABorderIcons) then
938    Result := Result or QtWindowContextHelpButtonHint;
939end;
940
941class function TQtWSCustomForm.GetQtFormStyle(const AFormStyle: TFormStyle): QtWindowFlags;
942begin
943  if AFormStyle in fsAllStayOnTop then
944    Result := QtWindowStaysOnTopHint
945  else
946    Result := 0;
947end;
948
949class procedure TQtWSCustomForm.UpdateWindowFlags(const AWidget: TQtMainWindow;
950  ABorderStyle: TFormBorderStyle; ABorderIcons: TBorderIcons; AFormStyle: TFormStyle);
951var
952  Flags: QtWindowFlags;
953  AVisible: Boolean;
954begin
955  AWidget.BeginUpdate;
956  AVisible := AWidget.getVisible;
957  Flags := GetQtBorderStyle(ABorderStyle) or GetQtFormStyle(AFormStyle) or GetQtBorderIcons(ABorderStyle, ABorderIcons);
958  if (Flags and QtFramelessWindowHint) = 0 then
959    Flags := Flags or QtWindowTitleHint or QtCustomizeWindowHint
960      or QtWindowCloseButtonHint;
961
962  if not (csDesigning in AWidget.LCLObject.ComponentState) then
963  begin
964    if (csNoFocus in TCustomForm(AWidget.LCLObject).ControlStyle) then
965    begin
966      {$IFDEF HASX11}
967      if ((QtVersionMajor = 4) and (QtVersionMinor >= 7)) or
968        (QtVersionMajor > 4) then
969      begin
970        if QtVersionMajor = 4 then
971          AWidget.setAttribute(132 {QtWA_X11DoNotAcceptFocus}, True)
972        else // Qt 5
973          AWidget.setAttribute(126 {QtWA_X11DoNotAcceptFocus}, True)
974      end;
975      {$ENDIF}
976      AWidget.setAttribute(QtWA_ShowWithoutActivating, True);
977    end;
978    AWidget.setWindowFlags(Flags);
979    if ABorderStyle in [bsDialog, bsNone, bsSingle] then
980      AWidget.Resize(AWidget.LCLObject.Width, AWidget.LCLObject.Height)
981    else
982    begin
983      // Reset constraints.
984      AWidget.setMinimumSize(QtMinimumWidgetSize, QtMinimumWidgetSize);
985      AWidget.setMaximumSize(QtMaximumWidgetSize, QtMaximumWidgetSize);
986    end;
987  end;
988
989  AWidget.setVisible(AVisible);
990  AWidget.EndUpdate;
991end;
992
993class function TQtWSCustomForm.GetDefaultClientRect(
994  const AWinControl: TWinControl; const aLeft, aTop, aWidth, aHeight: integer;
995  var aClientRect: TRect): boolean;
996var
997  AWin: TQtMainWindow;
998  ASize: TSize;
999begin
1000  Result := False;
1001  if AWinControl.HandleAllocated then
1002  begin
1003    {$IFDEF QTUSEACCURATEFRAME}
1004    if TQtMainWindow(AWinControl.Handle).IsFramedWidget then
1005    begin
1006      AClientRect := TQtMainWindow(AWinControl.Handle).getClientBounds;
1007      {$IFDEF DEBUGQTUSEACCURATEFRAME}
1008      DebugLn(Format('******TQtWSCustomForm.GetDefaultClientRect(%s): %s LCL l %d t %d w %d h %d',[dbgsName(AWinControl), dbgs(AClientRect), ALeft, ATop, aWidth, AHeight]));
1009      {$ENDIF}
1010      Result := True;
1011    end else
1012    {$ENDIF}
1013    if TQtMainWindow(AWinControl.Handle).testAttribute(QtWA_PendingResizeEvent) then
1014    begin
1015      if Assigned(TCustomForm(AWinControl).Menu) then
1016      begin
1017        AWin := TQtMainWindow(AWinControl.Handle);
1018        if Assigned(AWin.MenuBar) then
1019        begin
1020          AWin.MenuBar.sizeHint(@ASize);
1021          // geometry isn't updated yet
1022          if ASize.cy < 10 then
1023            ASize.cy := 0;
1024          // we must use real geometry, and then exclude menubar height.
1025          aClientRect := AWin.getGeometry;
1026          OffsetRect(aClientRect, -aClientRect.Left, -aClientRect.Top);
1027          dec(AClientRect.Bottom, ASize.cy);
1028          {$IFDEF VerboseQtResize}
1029          DebugLn('TQtWSCustomForm.getDefaultClientRect ',dbgsName(AWinControl),' ',dbgs(AWin.getClientBounds),' mnuBarHeight ',dbgs(AWin.MenuBar.getHeight),' ASize=',dbgs(ASize),' FINAL=',dbgs(AClientRect));
1030          {$ENDIF}
1031          Result := True;
1032        end;
1033      end;
1034    end;
1035  end;
1036end;
1037
1038class function TQtWSCustomForm.CanFocus(const AWinControl: TWinControl
1039  ): Boolean;
1040var
1041  Widget: TQtWidget;
1042begin
1043  if AWinControl.HandleAllocated then
1044  begin
1045    Widget := TQtWidget(AWinControl.Handle);
1046    Result := Widget.getVisible and Widget.getEnabled;
1047  end else
1048    Result := False;
1049end;
1050
1051{ TQtWSHintWindow }
1052
1053class function TQtWSHintWindow.CreateHandle(const AWinControl: TWinControl; const AParams: TCreateParams): TLCLIntfHandle;
1054var
1055  QtMainWindow: TQtMainWindow;
1056begin
1057  QtMainWindow := TQtHintWindow.Create(AWinControl, AParams);
1058  // Sets Various Events
1059  QtMainWindow.AttachEvents;
1060  Result := TLCLIntfHandle(QtMainWindow);
1061end;
1062
1063class procedure TQtWSHintWindow.ShowHide(const AWinControl: TWinControl);
1064var
1065  AWidget: TQtHintWindow;
1066begin
1067  if not WSCheckHandleAllocated(AWinControl, 'ShowHide') then
1068    Exit;
1069
1070  AWidget := TQtHintWindow(AWinControl.Handle);
1071
1072  AWidget.BeginUpdate;
1073  AWidget.setVisible(AWinControl.HandleObjectShouldBeVisible);
1074  AWidget.EndUpdate;
1075end;
1076
1077end.
1078