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