Mattias Gaertner schrieb:

BTW the SimpleLayout should *not* remember the bounds of *docked* forms, instead it should retain their *undocked* bounds, for use when such a form is undocked later.

That's just my preference: When a form is undocked it should not move. You can send me a patch to make this optional.

In the preparation of this patch I found a problem with the Source editor forms - they seem to have bad (default) values in UndockWidth/Height :-(

I didn't know where to send the patch, so I'll attach it to this message, for all interested readers. Above fix is made conditional, so that it can be tested easily.

The attached patch addresses the
handling of multi-monitor coordinates:
- Screen coordinates and bounds (forms.pp, screen.inc)
- allow for negative coordinates in Options Window
- and in CustomCoordinatesAreValid
and using the new methods:
- using Screen.FitToMonitor instead of agnostic checks
and a minor fix:
- properly handle negative Width/Height in GetDefaultBounds

Tested on Win32 with no docking packages installed.

DoDi
Index: ide/frames/window_options.lfm
===================================================================
--- ide/frames/window_options.lfm       (revision 31122)
+++ ide/frames/window_options.lfm       (working copy)
@@ -12,9 +12,9 @@
     AnchorSideTop.Control = Owner
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 22
+    Height = 19
     Top = 0
-    Width = 227
+    Width = 181
     Caption = 'SingleTaskBarButtonCheckBox'
     Enabled = False
     TabOrder = 0
@@ -25,9 +25,9 @@
     AnchorSideTop.Side = asrBottom
     AnchorSideRight.Side = asrBottom
     Left = 0
-    Height = 22
-    Top = 22
-    Width = 187
+    Height = 19
+    Top = 19
+    Width = 151
     Caption = 'HideIDEOnRunCheckBox'
     TabOrder = 1
   end
@@ -40,14 +40,14 @@
     AnchorSideBottom.Control = Owner
     AnchorSideBottom.Side = asrBottom
     Left = 0
-    Height = 357
-    Top = 116
+    Height = 372
+    Top = 101
     Width = 566
     Anchors = [akTop, akLeft, akRight, akBottom]
     BorderSpacing.Top = 6
     Caption = 'WindowPositionsGroupBox'
-    ClientHeight = 336
-    ClientWidth = 558
+    ClientHeight = 354
+    ClientWidth = 562
     TabOrder = 2
     object Bevel1: TBevel
       AnchorSideLeft.Control = WindowPositionsGroupBox
@@ -55,7 +55,7 @@
       AnchorSideTop.Side = asrCenter
       Left = 6
       Height = 3
-      Top = 169
+      Top = 168
       Width = 50
       BorderSpacing.Left = 6
     end
@@ -66,10 +66,10 @@
       AnchorSideTop.Side = asrCenter
       AnchorSideRight.Control = WindowPositionsGroupBox
       AnchorSideRight.Side = asrBottom
-      Left = 215
+      Left = 178
       Height = 3
-      Top = 169
-      Width = 337
+      Top = 168
+      Width = 378
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Left = 6
       BorderSpacing.Right = 6
@@ -79,9 +79,9 @@
       AnchorSideTop.Control = WindowPositionsListBox
       AnchorSideTop.Side = asrBottom
       Left = 70
-      Height = 18
+      Height = 16
       Top = 161
-      Width = 139
+      Width = 102
       BorderSpacing.Left = 70
       BorderSpacing.Top = 6
       Caption = 'lblWindowCaption'
@@ -93,10 +93,10 @@
       AnchorSideTop.Control = LeftEdit
       AnchorSideTop.Side = asrCenter
       AnchorSideRight.Control = LeftEdit
-      Left = 278
-      Height = 18
-      Top = 189
-      Width = 61
+      Left = 294
+      Height = 16
+      Top = 186
+      Width = 49
       Anchors = [akTop, akRight]
       BorderSpacing.Right = 3
       Caption = 'LeftLabel'
@@ -106,10 +106,10 @@
       AnchorSideTop.Control = TopEdit
       AnchorSideTop.Side = asrCenter
       AnchorSideRight.Control = TopEdit
-      Left = 281
-      Height = 18
-      Top = 222
-      Width = 58
+      Left = 293
+      Height = 16
+      Top = 215
+      Width = 50
       Anchors = [akTop, akRight]
       BorderSpacing.Right = 3
       Caption = 'TopLabel'
@@ -119,10 +119,10 @@
       AnchorSideTop.Control = WidthEdit
       AnchorSideTop.Side = asrCenter
       AnchorSideRight.Control = WidthEdit
-      Left = 400
-      Height = 18
-      Top = 189
-      Width = 74
+      Left = 417
+      Height = 16
+      Top = 186
+      Width = 61
       Anchors = [akTop, akRight]
       BorderSpacing.Right = 3
       Caption = 'WidthLabel'
@@ -132,10 +132,10 @@
       AnchorSideTop.Control = HeightEdit
       AnchorSideTop.Side = asrCenter
       AnchorSideRight.Control = HeightEdit
-      Left = 395
-      Height = 18
-      Top = 222
-      Width = 79
+      Left = 413
+      Height = 16
+      Top = 215
+      Width = 65
       Anchors = [akTop, akRight]
       BorderSpacing.Right = 3
       Caption = 'HeightLabel'
@@ -149,7 +149,7 @@
       Left = 6
       Height = 149
       Top = 6
-      Width = 546
+      Width = 550
       Anchors = [akTop, akLeft, akRight]
       BorderSpacing.Around = 6
       ItemHeight = 0
@@ -161,80 +161,79 @@
       AnchorSideTop.Control = lblWindowCaption
       AnchorSideTop.Side = asrBottom
       Left = 6
-      Height = 22
-      Top = 185
-      Width = 288
+      Height = 19
+      Top = 183
+      Width = 233
       BorderSpacing.Around = 6
       Caption = 'UseWindowManagerSettingRadioButton'
       Checked = True
-      State = cbChecked
       TabOrder = 1
+      TabStop = True
     end
     object DefaultRadioButton: TRadioButton
       AnchorSideLeft.Control = WindowPositionsGroupBox
       AnchorSideTop.Control = UseWindowManagerSettingRadioButton
       AnchorSideTop.Side = asrBottom
       Left = 6
-      Height = 22
-      Top = 213
-      Width = 156
+      Height = 19
+      Top = 208
+      Width = 124
       BorderSpacing.Around = 6
       Caption = 'DefaultRadioButton'
       TabOrder = 2
-      TabStop = False
     end
     object RestoreWindowGeometryRadioButton: TRadioButton
       AnchorSideLeft.Control = WindowPositionsGroupBox
       AnchorSideTop.Control = DefaultRadioButton
       AnchorSideTop.Side = asrBottom
       Left = 6
-      Height = 22
-      Top = 241
-      Width = 274
+      Height = 19
+      Top = 233
+      Width = 221
       BorderSpacing.Around = 6
       Caption = 'RestoreWindowGeometryRadioButton'
       TabOrder = 3
-      TabStop = False
     end
     object CustomPositionRadioButton: TRadioButton
       AnchorSideLeft.Control = WindowPositionsGroupBox
       AnchorSideTop.Control = RestoreWindowGeometryRadioButton
       AnchorSideTop.Side = asrBottom
       Left = 6
-      Height = 22
-      Top = 269
-      Width = 210
+      Height = 19
+      Top = 258
+      Width = 171
       BorderSpacing.Around = 6
       Caption = 'CustomPositionRadioButton'
       TabOrder = 4
-      TabStop = False
     end
     object LeftEdit: TSpinEdit
       AnchorSideTop.Control = lblWindowCaption
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = WidthEdit
-      Left = 342
-      Height = 27
-      Top = 185
+      Left = 346
+      Height = 23
+      Top = 183
       Width = 75
       Anchors = [akTop, akRight]
       BorderSpacing.Top = 6
       BorderSpacing.Right = 60
       MaxValue = 4096
+      MinValue = -4096
       TabOrder = 5
     end
     object TopEdit: TSpinEdit
       AnchorSideTop.Control = LeftEdit
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = HeightEdit
-      Left = 342
-      Height = 27
-      Top = 218
+      Left = 346
+      Height = 23
+      Top = 212
       Width = 75
       Anchors = [akTop, akRight]
       BorderSpacing.Top = 6
       BorderSpacing.Right = 60
       MaxValue = 4096
+      MinValue = -4096
       TabOrder = 6
     end
     object WidthEdit: TSpinEdit
@@ -242,39 +241,43 @@
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = WindowPositionsGroupBox
       AnchorSideRight.Side = asrBottom
-      Left = 477
-      Height = 27
-      Top = 185
+      Left = 481
+      Height = 23
+      Top = 183
       Width = 75
       Anchors = [akTop, akRight]
       BorderSpacing.Top = 6
       BorderSpacing.Right = 6
       MaxValue = 4096
+      MinValue = 100
       TabOrder = 7
+      Value = 100
     end
     object HeightEdit: TSpinEdit
       AnchorSideTop.Control = WidthEdit
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = WindowPositionsGroupBox
       AnchorSideRight.Side = asrBottom
-      Left = 477
-      Height = 27
-      Top = 218
+      Left = 481
+      Height = 23
+      Top = 212
       Width = 75
       Anchors = [akTop, akRight]
       BorderSpacing.Top = 6
       BorderSpacing.Right = 6
       MaxValue = 4096
+      MinValue = 100
       TabOrder = 8
+      Value = 100
     end
     object GetWindowPositionButton: TButton
       AnchorSideTop.Control = TopEdit
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = ApplyButton
-      Left = 260
-      Height = 27
-      Top = 251
-      Width = 188
+      Left = 290
+      Height = 25
+      Top = 241
+      Width = 167
       Anchors = [akTop, akRight]
       AutoSize = True
       BorderSpacing.Around = 6
@@ -288,10 +291,10 @@
       AnchorSideTop.Side = asrBottom
       AnchorSideRight.Control = WindowPositionsGroupBox
       AnchorSideRight.Side = asrBottom
-      Left = 454
-      Height = 27
-      Top = 251
-      Width = 98
+      Left = 463
+      Height = 25
+      Top = 241
+      Width = 93
       Anchors = [akTop, akRight]
       AutoSize = True
       BorderSpacing.Around = 6
@@ -306,9 +309,9 @@
     AnchorSideTop.Control = HideIDEOnRunCheckBox
     AnchorSideTop.Side = asrBottom
     Left = 0
-    Height = 22
-    Top = 44
-    Width = 222
+    Height = 19
+    Top = 38
+    Width = 176
     Caption = 'HideMessagesIconsCheckBox'
     TabOrder = 3
   end
@@ -317,9 +320,9 @@
     AnchorSideTop.Control = HideMessagesIconsCheckBox
     AnchorSideTop.Side = asrBottom
     Left = 0
-    Height = 22
-    Top = 66
-    Width = 235
+    Height = 19
+    Top = 57
+    Width = 186
     Caption = 'TitleStartsWithProjectCheckBox'
     ParentShowHint = False
     ShowHint = True
@@ -330,9 +333,9 @@
     AnchorSideTop.Control = TitleStartsWithProjectCheckBox
     AnchorSideTop.Side = asrBottom
     Left = 0
-    Height = 22
-    Top = 88
-    Width = 218
+    Height = 19
+    Top = 76
+    Width = 173
     Caption = 'ProjectDirInIdeTitleCheckBox'
     ParentShowHint = False
     ShowHint = True
Index: ideintf/idewindowintf.pas
===================================================================
--- ideintf/idewindowintf.pas   (revision 31122)
+++ ideintf/idewindowintf.pas   (working copy)
@@ -749,7 +749,7 @@
 
 function TSimpleWindowLayout.CustomCoordinatesAreValid: boolean;
 begin
-  Result:=(Width>0) and (Height>0) and (Left>10-Width) and (Top>10-Height);
+  Result:=(Width>0) and (Height>0); //top and left can be negative
 end;
 
 procedure TSimpleWindowLayout.CloseForm;
@@ -828,8 +828,13 @@
       p:=Point(0,0);
     Left:=Form.Left+p.X;
     Top:=Form.Top+p.Y;
+  {$IFDEF new}
+    Width:=Form.UndockWidth;
+    Height:=Form.UndockHeight;
+  {$ELSE}
     Width:=Form.Width;
     Height:=Form.Height;
+  {$ENDIF}
   end;
 end;
 
@@ -1053,20 +1058,7 @@
             if NewBounds.Bottom-NewBounds.Top<60 then
               NewBounds.Bottom:=NewBounds.Top+60;
             // move to visible area
-            if NewBounds.Right<60 then
-              OffsetRect(NewBounds,60-NewBounds.Right,0);
-            if NewBounds.Bottom<60 then
-              OffsetRect(NewBounds,0,60-NewBounds.Bottom);
-            if NewBounds.Left>Screen.DesktopWidth-60 then begin
-              i:=(Screen.DesktopWidth-60)-NewBounds.Left;
-              NewBounds.Left := Screen.DesktopWidth-60;
-              NewBounds.Right := NewBounds.Right + i;
-            end;
-            if NewBounds.Top>Screen.DesktopHeight-60 then begin
-              i:=(Screen.DesktopHeight-60)-NewBounds.Top;
-              NewBounds.Top := Screen.DesktopHeight-60;
-              NewBounds.Bottom := NewBounds.Bottom + i;
-            end;
+            NewBounds := Screen.FitToMonitor(NewBounds);
             // set bounds (do not use SetRestoredBounds - that flickers with 
the current LCL implementation)
             AForm.SetBounds(NewBounds.Left,NewBounds.Top,
                             NewBounds.Right-NewBounds.Left,
@@ -1148,11 +1140,7 @@
       {$IFDEF VerboseIDEDocking}
       debugln(['TSimpleWindowLayoutList.ApplyAndShow ',DbgSName(AForm),' 
NewBounds=',dbgs(NewBounds)]);
       {$ENDIF}
-      NewBounds.Left:=Min(10000,Max(-10000,NewBounds.Left));
-      NewBounds.Top:=Min(10000,Max(-10000,NewBounds.Top));
-      NewBounds.Right:=Max(NewBounds.Left+100,NewBounds.Right);
-      NewBounds.Bottom:=Max(NewBounds.Top+100,NewBounds.Bottom);
-      AForm.BoundsRect:=NewBounds;
+      AForm.BoundsRect:= Screen.FitToMonitor(NewBounds);
     end;
   finally
     if (AForm.WindowState in [wsNormal,wsMaximized]) and BringToFront then
@@ -1279,7 +1267,7 @@
   else
     aRight:=StrToIntDef(Right,0);
   if aRight<0 then
-    aRight:=Screen.Width-aRight
+    aRight:=Screen.Width+aRight //is < 0!
   else if (Right<>'') and (Right[1]='+') then
     inc(aRight,DefBounds.Left);
   DefBounds.Right:=aRight;
@@ -1291,7 +1279,7 @@
   else
     aBottom:=StrToIntDef(Bottom,0);
   if aBottom<0 then
-    aBottom:=Screen.Height-aBottom
+    aBottom:=Screen.Height+aBottom //is < 0!
   else if (Bottom<>'') and (Bottom[1]='+') then
     inc(aBottom,DefBounds.Top);
   DefBounds.Bottom:=aBottom;
Index: lcl/forms.pp
===================================================================
--- lcl/forms.pp        (revision 31122)
+++ lcl/forms.pp        (working copy)
@@ -912,6 +912,7 @@
     FActiveControl: TWinControl;
     FActiveCustomForm: TCustomForm;
     FActiveForm: TForm;
+    FBoundsRect: TRect;
     FCursor: TCursor;
     FCursorMap: TMap;
     FCustomForms: TFPList;
@@ -952,6 +953,7 @@
     function GetMonitor(Index: Integer): TMonitor;
     function GetMonitorCount: Integer;
     function GetPrimaryMonitor: TMonitor;
+    function GetBoundsRect: TRect;
     function GetWidth : Integer;
     procedure AddForm(AForm: TCustomForm);
     procedure RemoveForm(AForm: TCustomForm);
@@ -1016,6 +1018,9 @@
 
     function DisableForms(SkipForm: TCustomForm; DisabledList: TList = nil): 
TList;
     procedure EnableForms(var AFormList: TList);
+    function FitInto(const src, dst: TRect): TRect;
+    function FitToScreen(const src: TRect): TRect;
+    function FitToMonitor(const src: TRect): TRect;
     function MonitorFromPoint(const Point: TPoint;
       MonitorDefault: TMonitorDefaultTo = mdNearest): TMonitor;
     function MonitorFromRect(const Rect: TRect;
@@ -1026,6 +1031,7 @@
     property ActiveControl: TWinControl read FActiveControl;
     property ActiveCustomForm: TCustomForm read FActiveCustomForm;
     property ActiveForm: TForm read FActiveForm;
+    property BoundsRect: TRect read GetBoundsRect;
     property Cursor: TCursor read FCursor write SetCursor;
     property Cursors[Index: Integer]: HCURSOR read GetCursors write SetCursors;
     property CustomFormCount: Integer read GetCustomFormCount;
Index: lcl/include/screen.inc
===================================================================
--- lcl/include/screen.inc      (revision 31122)
+++ lcl/include/screen.inc      (working copy)
@@ -419,6 +419,52 @@
   FreeAndNil(AFormList);
 end;
 
+function TScreen.FitInto(const src, dst: TRect): TRect;
+begin
+(* Adjust src to fit into dst.
+   Keep src extent if possible.
+*)
+  if src.Right > dst.Right then begin
+    //shift left
+    Result.Right := dst.Right;
+    Result.Left := Max(dst.Left, Result.Right - (src.Right - src.Left));
+  end else if src.Left < dst.Left then begin
+    //shift right
+    Result.Left := src.Left;
+    Result.Right := Min(dst.Right, Result.Left + (src.Right - src.Left));
+  end else begin
+    Result.Left := src.Left;
+    Result.Right:= src.Right;
+  end;
+  if src.Bottom > dst.Bottom then begin
+    //shift up
+    Result.Bottom := dst.Bottom;
+    Result.Top := Max(dst.Top, Result.Bottom - (src.Bottom - src.Top));
+  end else if src.Top < dst.Top then begin
+    //shift down
+    Result.Top := dst.Top;
+    Result.Bottom := Min(dst.Bottom, Result.Top + (src.Bottom - src.Top));
+  end else begin
+    Result.Top := src.Top;
+    Result.Bottom := src.Bottom;
+  end;
+end;
+
+function TScreen.FitToScreen(const src: TRect): TRect;
+begin
+  Result := FitInto(src, BoundsRect);
+end;
+
+function TScreen.FitToMonitor(const src: TRect): TRect;
+var
+  m: TMonitor;
+begin
+  m := MonitorFromPoint(src.TopLeft);
+  if m = nil then
+    m := Monitors[0];
+  Result := FitInto(src, m.BoundsRect);
+end;
+
 function TScreen.MonitorFromPoint(const Point: TPoint;
   MonitorDefault: TMonitorDefaultTo): TMonitor;
 var
@@ -745,6 +791,27 @@
   Result := nil;
 end;
 
+function TScreen.GetBoundsRect: TRect;
+var
+  i: integer;
+  m: TMonitor;
+  r: TRect;
+begin
+  if FBoundsRect.Right = 0 then begin
+    FBoundsRect := Monitors[0].BoundsRect;
+    for i := 1 to MonitorCount - 1 do begin
+      //merge monitor bounds
+      r := Monitors[i].BoundsRect;
+      if r.Top < FBoundsRect.Top then FBoundsRect.Top := r.Top;
+      if r.Bottom > FBoundsRect.Bottom then FBoundsRect.Bottom := r.Bottom;
+      if r.Left < FBoundsRect.Left then FBoundsRect.Left := r.Left;
+      if r.Right > FBoundsRect.Right then FBoundsRect.Right := r.Right;
+    end;
+    //todo: exclude TaskBar
+  end;
+  Result := FBoundsRect;
+end;
+
 function TScreen.GetSystemFont: TFont;
 begin
   if (FSystemFont = nil) then
--
_______________________________________________
Lazarus mailing list
[email protected]
http://lists.lazarus.freepascal.org/mailman/listinfo/lazarus

Reply via email to