mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-12-04 09:57:15 +01:00
GTK2 ScrollWindowEx / rewrite
git-svn-id: trunk@34878 -
This commit is contained in:
parent
d3a30108d6
commit
de7c2a8a60
@ -33,6 +33,8 @@
|
||||
// {$DEFINE ASSERT_IS_ON}
|
||||
{$EndIf}
|
||||
|
||||
{off $define VerboseScrollWindowEx}
|
||||
|
||||
const
|
||||
BOOL_TEXT: array[Boolean] of string = ('False', 'True');
|
||||
|
||||
@ -7386,13 +7388,14 @@ var
|
||||
Window: PGdkWindow;
|
||||
{$ifdef GTK_2_8}
|
||||
Region: PGdkRegion;
|
||||
Rect1: TGdkRectangle; // full source rect
|
||||
Rect1a: TGdkRectangle; // source rect for clip
|
||||
RClient, RFullSource, RUsableSource, RTarget, RUsableTarget: TRect;
|
||||
Rect1: TGdkRectangle;
|
||||
Rect2: TRect; // area to invalidate
|
||||
WidgetInfo: PWidgetInfo;
|
||||
{$ENDIF}
|
||||
begin
|
||||
Result := False;
|
||||
if (dy = 0) and (dx = 0) then exit;
|
||||
{$IFDEF DisableGtk2ScrollWindow}
|
||||
exit;
|
||||
{$ENDIF}
|
||||
@ -7407,90 +7410,148 @@ begin
|
||||
Window:=GetControlWindow(Widget);
|
||||
if Window = nil then exit;
|
||||
{$ifdef GTK_2_8}
|
||||
Rect1.X := 0;//Widget^.Allocation.X;
|
||||
Rect1.Y := 0; //Widget^.Allocation.Y;
|
||||
Rect1.width := Widget^.Allocation.Width;
|
||||
Rect1.height := Widget^.Allocation.Height;
|
||||
//DebugLn(['ScrollWindowEx A ', dbgs(Rect1),' dy=',dy, ' scroll=',dbgs(prcScroll^), ' clip=',dbgs(prcClip^)]);
|
||||
RClient.Left := 0;//Widget^.Allocation.Left;
|
||||
RClient.Top := 0; //Widget^.Allocation.Top;
|
||||
RClient.Right := Widget^.Allocation.width;
|
||||
RClient.Bottom := Widget^.Allocation.height;
|
||||
RFullSource := RClient;
|
||||
{$ifdef VerboseScrollWindowEx}
|
||||
DebugLn(['ScrollWindowEx A RClient=', dbgs(RClient),' dy=',dy, ' scroll=',dbgs(prcScroll^), ' clip=',dbgs(prcClip^)]);
|
||||
{$ENDIF}
|
||||
|
||||
// Any part of RFullSource, that is not targeted by the move must later be invalidated
|
||||
if PrcScroll <> nil then
|
||||
begin
|
||||
Rect1.x := Max(Rect1.x, PrcScroll^.Left);
|
||||
Rect1.y := Max(Rect1.y, PrcScroll^.Top);
|
||||
Rect1.width := Min(Rect1.width - Rect1.x, PrcScroll^.Right - PrcScroll^.Left);
|
||||
//Rect1.width := Min(Rect1.width - (Rect1.x - Widget^.Allocation.X), PrcScroll^.Right - PrcScroll^.Left);
|
||||
Rect1.height := Min(Rect1.height - Rect1.y, PrcScroll^.Bottom - PrcScroll^.Top);
|
||||
RFullSource.Left := Max(RClient.Left, PrcScroll^.Left);
|
||||
RFullSource.Top := Max(RClient.Top, PrcScroll^.Top);
|
||||
RFullSource.Right := Min(RClient.Right, PrcScroll^.Right);
|
||||
RFullSource.Bottom := Min(RClient.Bottom, PrcScroll^.Bottom);
|
||||
end;
|
||||
if (PrcClip <> nil) then begin
|
||||
// Limit the source rect, so it will fit into PrcClip
|
||||
Rect1a.x := Max(PrcClip^.Left - dx, Rect1.x);
|
||||
Rect1a.y := Max(PrcClip^.Top - dy, Rect1.y);
|
||||
Rect1a.width := Min(PrcClip^.Right - dx - Rect1.x, Rect1.width);
|
||||
Rect1a.height := Min(PrcClip^.Bottom - dy - Rect1.y, Rect1.height);
|
||||
end
|
||||
else
|
||||
Rect1a := Rect1;
|
||||
//DebugLn(['ScrollWindowEx B ', dbgs(Rect1), ' ', dbgs(Rect1a)]);
|
||||
|
||||
// Target is expected to be completly filled with valid content by move,
|
||||
// any part that can not be filled must be invalidated
|
||||
RTarget.Left := Max(RClient.Left, RFullSource.Left + dx);
|
||||
RTarget.Top := Max(RClient.Top, RFullSource.Top + dy);
|
||||
RTarget.Right := Min(RClient.Right, RFullSource.Right + dx);
|
||||
RTarget.Bottom := Min(RClient.Bottom, RFullSource.Bottom + dy);
|
||||
if (PrcClip <> nil) then begin
|
||||
RTarget.Left := Max(RTarget.Left, prcClip^.Left);
|
||||
RTarget.Top := Max(RTarget.Top, prcClip^.Top);
|
||||
RTarget.Right := Min(RTarget.Right, prcClip^.Right);
|
||||
RTarget.Bottom := Min(RTarget.Bottom, prcClip^.Bottom);
|
||||
end;
|
||||
|
||||
// Only Source that will fit into target
|
||||
RUsableSource.Left := Max(RTarget.Left - dx, RFullSource.Left);
|
||||
RUsableSource.Top := Max(RTarget.Top - dy, RFullSource.Top);
|
||||
RUsableSource.Right := Min(RTarget.Right - dx, RFullSource.Right);
|
||||
RUsableSource.Bottom := Min(RTarget.Bottom - dy, RFullSource.Bottom);
|
||||
{$ifdef VerboseScrollWindowEx}
|
||||
DebugLn(['ScrollWindowEx B RFullSource=', dbgs(RFullSource), ' RUsableSource=', dbgs(RUsableSource)]);
|
||||
{$ENDIF}
|
||||
|
||||
// And also, only Source that is valid
|
||||
WidgetInfo := GetWidgetInfo(Widget, False);
|
||||
if WidgetInfo <> nil then begin
|
||||
//DebugLn(['ScrollWindowEx C ', dbgs(WidgetInfo^.UpdateRect)]);
|
||||
{$ifdef VerboseScrollWindowEx}
|
||||
DebugLn(['ScrollWindowEx C ', dbgs(WidgetInfo^.UpdateRect)]);
|
||||
{$ENDIF}
|
||||
// exclude allready invalidated area
|
||||
if (WidgetInfo^.UpdateRect.Right >= Rect1a.x + Rect1a.width) and
|
||||
(WidgetInfo^.UpdateRect.Left <= Rect1a.x)
|
||||
then begin
|
||||
if (dy < 0) and (WidgetInfo^.UpdateRect.Bottom > 0) then
|
||||
Rect1a.Height := Min(Rect1a.y + Rect1a.height,
|
||||
WidgetInfo^.UpdateRect.Top) - Rect1a.y;
|
||||
if (dy > 0) and (Rect1a.y < WidgetInfo^.UpdateRect.Bottom) then begin
|
||||
Rect1a.height := Rect1a.height - (WidgetInfo^.UpdateRect.Bottom - Rect1a.y);
|
||||
Rect1a.y := WidgetInfo^.UpdateRect.Bottom;
|
||||
end;
|
||||
end;
|
||||
// TODO: content moved into currently invalidated space, may reduce the inval rect
|
||||
// "UpdateRect.Bottom > 0" => there is an UpdateRect / Top is valid
|
||||
if (dy < 0) and (WidgetInfo^.UpdateRect.Bottom > 0) then
|
||||
RUsableSource.Bottom := Min(RUsableSource.Bottom, WidgetInfo^.UpdateRect.Top);
|
||||
if (dy > 0) and (RUsableSource.Top < WidgetInfo^.UpdateRect.Bottom) then
|
||||
RUsableSource.Top := WidgetInfo^.UpdateRect.Bottom;
|
||||
|
||||
if (WidgetInfo^.UpdateRect.Bottom >= Rect1a.y + Rect1a.height) and
|
||||
(WidgetInfo^.UpdateRect.Top <= Rect1a.y)
|
||||
then begin
|
||||
if (dx < 0) and (WidgetInfo^.UpdateRect.Right > 0) then
|
||||
Rect1a.width := Min(Rect1a.x + Rect1a.width,
|
||||
WidgetInfo^.UpdateRect.Left) - Rect1a.x;
|
||||
if (dx > 0) and (Rect1a.x < WidgetInfo^.UpdateRect.Right) then begin
|
||||
Rect1a.width := Rect1a.width - (WidgetInfo^.UpdateRect.Right - Rect1a.x);
|
||||
Rect1a.x := WidgetInfo^.UpdateRect.Right;
|
||||
end;
|
||||
end;
|
||||
if (dx < 0) and (WidgetInfo^.UpdateRect.Right > 0) then
|
||||
RUsableSource.Right := Min(RUsableSource.Right, WidgetInfo^.UpdateRect.Left);
|
||||
if (dx > 0) and (RUsableSource.Left < WidgetInfo^.UpdateRect.Right) then
|
||||
RUsableSource.Left := WidgetInfo^.UpdateRect.Right;
|
||||
end;
|
||||
//DebugLn(['ScrollWindowEx D ', dbgs(Rect1a)]);
|
||||
{$ifdef VerboseScrollWindowEx}
|
||||
DebugLn(['ScrollWindowEx D RUsableSource=', dbgs(RUsableSource)]);
|
||||
{$ENDIF}
|
||||
|
||||
// TODO: content moved into currently invalidated space, may reduce the inval rect
|
||||
// All of RUsableTarget should be validated;
|
||||
RUsableTarget.Left := Max(RTarget.Left, RUsableSource.Left + dx);
|
||||
RUsableTarget.Top := Max(RTarget.Top, RUsableSource.Top + dy);
|
||||
RUsableTarget.Right := Min(RTarget.Right, RUsableSource.Right + dx);
|
||||
RUsableTarget.Bottom := Min(RTarget.Bottom, RUsableSource.Bottom + dy);
|
||||
{$ifdef VerboseScrollWindowEx}
|
||||
DebugLn(['ScrollWindowEx D RUsableTarget=', dbgs(RUsableTarget)]);
|
||||
{$ENDIF}
|
||||
|
||||
if (Rect1a.height > 0) and (Rect1a.width > 0) then begin
|
||||
// Calculate area to invalidate
|
||||
// Rect1a.y may either be equal or greater than Rect1.y
|
||||
// Rect1a.height may either be equal or less than Rect1.height
|
||||
if (dy < 0) then
|
||||
Rect2 := Rect(Rect1.x, Rect1a.y + Rect1a.height + dy,
|
||||
Rect1.width, Rect1.y + Rect1.height);
|
||||
if dy > 0 then
|
||||
Rect2 := Rect(Rect1.x, Rect1.y,
|
||||
Rect1.width, Rect1a.y + dy);
|
||||
// Todo dx
|
||||
//DebugLn(['ScrollWindowEx E ', dbgs(Rect2)]);
|
||||
Rect1 := GdkRectFromRect(RUsableSource);
|
||||
|
||||
Region := gdk_region_rectangle(@Rect1a);
|
||||
if (Rect1.height > 0) and (Rect1.width > 0) then begin
|
||||
Region := gdk_region_rectangle(@Rect1);
|
||||
gdk_window_move_region(Window, Region, dx, dy);
|
||||
|
||||
//invalidate
|
||||
If RUsableTarget.Left > RFullSource.Left then begin
|
||||
Rect2 := RFullSource;
|
||||
Rect2.Right:= RUsableTarget.Left;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate Src Left', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
If RUsableTarget.Right < RFullSource.Right then begin
|
||||
Rect2 := RFullSource;
|
||||
Rect2.Left:= RUsableTarget.Right;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate Src Right', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
If RUsableTarget.Top > RFullSource.Top then begin
|
||||
Rect2 := RFullSource;
|
||||
Rect2.Bottom:= RUsableTarget.Top;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate Src Top', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
If RUsableTarget.Bottom < RFullSource.Bottom then begin
|
||||
Rect2 := RFullSource;
|
||||
Rect2.Top:= RUsableTarget.Bottom;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate Src Bottom', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
|
||||
If RUsableTarget.Left > RTarget.Left then begin
|
||||
Rect2 := RTarget;
|
||||
Rect2.Right:= RUsableTarget.Left;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate TARGET Left', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
If RUsableTarget.Right < RTarget.Right then begin
|
||||
Rect2 := RTarget;
|
||||
Rect2.Left:= RUsableTarget.Right;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate TARGET Right', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
If RUsableTarget.Top > RTarget.Top then begin
|
||||
Rect2 := RTarget;
|
||||
Rect2.Bottom:= RUsableTarget.Top;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate TARGET Top', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
|
||||
If RUsableTarget.Bottom < RTarget.Bottom then begin
|
||||
Rect2 := RTarget;
|
||||
Rect2.Top:= RUsableTarget.Bottom;
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate TARGET Bottom', dbgs(Rect2)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
end;
|
||||
end
|
||||
else begin
|
||||
// invalidate, nothing to scroll
|
||||
Rect2 := Rect(Rect1.x, Rect1.y, Rect1.x + Rect1.width, Rect1.y + Rect1.height);
|
||||
//DebugLn(['ScrollWindowEx F ', dbgs(Rect2)]);
|
||||
{$ifdef VerboseScrollWindowEx}DebugLn(['ScrollWindowEx Invalidate all', dbgs(RUsableSource)]);{$ENDIF}
|
||||
InvalidateRect(hWnd, @RFullSource, false);
|
||||
InvalidateRect(hWnd, @RTarget, false);
|
||||
end;
|
||||
|
||||
// Rect2 includes the Area at the scroll-in side of Rect1
|
||||
// gdk_window_move_region is supposed to have invalidated it, but some
|
||||
// implementations seem not to do this. (bug 14297)
|
||||
if (dy <> 0) then
|
||||
InvalidateRect(hWnd, @Rect2, false);
|
||||
{$ELSE}
|
||||
gdk_window_scroll(Window, dx, dy);
|
||||
{$ENDIF}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user