Recent

Author Topic: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?  (Read 984 times)

d7_2_laz

  • Full Member
  • ***
  • Posts: 110
On the last meters when porting my Delphi 7 app to Lazarus 2.0.12 (Windows x64 only) i got a crash at Drop and don't know if i did something did illegitimate.
What did i try?
I've an already established DragDrop functionality established with pre-Lazarus (Delphi7) means and noticed some drag animation effects were missing. I got aware that Lazarus will work differently...
After studying some threads in the forum i tried to use the example “dragimagelist” for my use cae.
This is a custom treeview where i have copies from system icons stored in an ImageList. Planning  to use those icons as ghost images (node icons as ghost image).
Is there something illegitimate so far? I'm needing the DragObject for the ghost images only.
That what i did:
Code: Pascal  [Select][+][-]
  1. constructor TMyDragObject.CreateWith(AControl: TControl; il: TImageList; imgidx: Integer);
  2. var Bitmap: TBitmap;
  3. begin
  4.   inherited Create(AControl);
  5.   FDragImages := TDragImageList.Create(AControl);
  6.   AlwaysShowDragImages := True;
  7.   Bitmap := TBitmap.Create;
  8.   Bitmap.Width := 16;
  9.   Bitmap.Height := 16;
  10.   Bitmap.Canvas.Changed;
  11.   FDragImages.Width := Bitmap.Width;
  12.   FDragImages.Height := Bitmap.Height;
  13. ImageList_Draw(il.ResolutionByIndex[0].Reference.Handle, imgidx, Bitmap.Canvas.Handle, 0, 0, ILD_TRANSPARENT);
  14.   FDragImages.Add(Bitmap, nil);
  15.   Bitmap.Free;
  16. end;

At OnStartDrag i do:

Code: Pascal  [Select][+][-]
  1. procedure TMyCustomTreeview.DirTreeDoOnStartDrag(Sender: TObject; var DragObject: TDragObject);
  2. var imgidx : Integer;
  3. begin
  4.     imgidx := 15;    // hard-coded temporarely simply for testing
  5.     FDragObject := TMyDragObject.CreateWith(Sender as TControl, FTvImageList, imgidx);
  6.     DragObject := FDragObject;
  7. end;

Works quite fine so far (although the image is not quite transparent yet, well anyhow), but it crashes when entering the OnDragDrop event.

At OnDragOver i did nothing special. It's simply decided where to Accept Drag and where not.

At OnDragDrop i try at first to HideDragImage and Free it (it is stored in FDragObject)
But before that it directly crashes (SIGSEV) when hen having entered the procedure.

It crashes here: in dragimagelist.inc (it halts in first line):

Code: Pascal  [Select][+][-]
  1. procedure TDragImageListResolution.HideDragImage;
  2. begin
  3.   if Dragging then
  4.     TWSDragImageListResolutionClass(WidgetSetClass).HideDragImage(Self, 0, False);
  5. end;

If i directly look onto the WM_RBUTTONUP message: that will be entered, but crashes here immediately.

Does anybody having done such similar has an idea where the flaw might be located?

engkin

  • Hero Member
  • *****
  • Posts: 2721
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #1 on: April 20, 2021, 05:35:50 pm »
At OnDragDrop i try at first to HideDragImage and Free it (it is stored in FDragObject)

This sounds wrong to me.

Does it crash if you don't do any thing in OnDragDrop?

Check this thread.

d7_2_laz

  • Full Member
  • ***
  • Posts: 110
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #2 on: April 20, 2021, 07:20:08 pm »
Hello engkin, thanks!
Yes, it doesn't reallly reach the first statement within DragDrop procedure. As it behaves the same with an "exit" as first statement or an empty procedure.

The same if i shrink  the DragOver callback (for test:) to contain only an Accept := true;  and nothing else.

Follwing the recommendation in the link i replaced the TDragControlObject by TDragControlObjectEx
(TMyDragObject = class(TDragControlObjectEx).   And, for test,  removed the destructor from TMyDragObject  (as well as the intermediate variable FDragObject) . - No difference.

In my approach i do not paint a Control (eg. Button) into the dragimage, but pickup a bitmap from an imagelist.  Assuming that should not be relevant. (instead of this i could try to fetch the treenode for painting, hm yes).But how the bitmap is painted chouldn't play a role, right?

The crash is directly at leftbutton up. And it appears to me the memory for the property "Dragging" could not be accessed.
The call stack is (the crashing routine on top):

TDragImageListResolution.HideDragImage
TDragImageList.HideDragImage
TDragObject.HideDragImage
TCustomTreeView.DoDragMsg           (case dmDragLeave .. -> ADragObject.HideDragImage;  )
TDragDockCommon.SendDragMessage       (--> AControl.DoDragMsg)
TDragDockCommon.SendCmDragMsg
TDragPerformer.DragStop
TDragManagerDefault.DragStop
TDragManagerDefault.MouseUp
TControl.DoMouseUp




jamie

  • Hero Member
  • *****
  • Posts: 4468
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #3 on: April 21, 2021, 01:14:30 am »
Does this help you?

The only true wisdom is knowing you know nothing

d7_2_laz

  • Full Member
  • ***
  • Posts: 110
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #4 on: April 21, 2021, 10:09:11 am »
Hey jamie .. and thanks again!   :)

Not really - the context is a bit too far away from my scenario
and ... uh! .... with this project1, dragging the button around i got an error box / heap dump  (image attached).

The good news is: i could recreate the problem exactly with a little testcase (nearly done)
and i'll post it here later the day [offline now for some hours].
So it should be easily seen what i did wrong. Myself i do not see it, probably a newbie user error.

trev

  • Global Moderator
  • Hero Member
  • *****
  • Posts: 1444
  • Former Delphi 1-7, 10.2 user
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #5 on: April 21, 2021, 12:40:41 pm »
uh! .... with this project1, dragging the button around i got an error box / heap dump  (image attached).

Not actually an error, just an info dump showing no error  ;)
Lazarus 2.1 r65061 FPC 3.3.1 r49223 macOS 10.14.6 Xcode 11.3.1
Lazarus 2.1 r65070 FPC 3.3.1 r49223 macOS 11.2.3 aarch64 Xcode 12.4
Lazarus 2.1 r61574 FPC 3.3.1 r42318 FreeBSD 12.1 amd64 VMware VM
Lazarus 2.1 r61574 FPC 3.0.4 Ubuntu 20.04 Parallels VM
Lazarus 2.0.10 FPC 3.2.0 Win10 Parallels VM

d7_2_laz

  • Full Member
  • ***
  • Posts: 110
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #6 on: April 21, 2021, 04:10:21 pm »
Quote
just an info dump
Oh, didn't know that yet, obviously it's from project options, debugger, Use heaptrace
Great to know, it's valuable info about allocated / freed / unfreed memory - thanks trev!

Attached the the test case. It does not contain any functionality but should be sufficient where it crashes when dropping a selected treenode onto another.
I'm very excited to find out where is my mistake,

d7_2_laz

  • Full Member
  • ***
  • Posts: 110
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #7 on: April 22, 2021, 09:56:55 am »
Is there anybody who even did try the test case?

dseligo

  • Sr. Member
  • ****
  • Posts: 252
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #8 on: April 22, 2021, 10:51:22 am »
I looked at it.
If I comment 'function GetDragImages: TDragImageList; override;' in TMyDragObject (and implementation below) then there is no SIGSEV.
Maybe you didn't implement this override function correctly?

d7_2_laz

  • Full Member
  • ***
  • Posts: 110
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #9 on: April 22, 2021, 11:46:11 am »
Many thanks dseligo!
yes, the exception will disappear when commenting out the function GetDragImages,
... but the bitmapped drag image won't appear either any longer (loss of fhe intended functionality).

The function had been 1:2 picked up from the examples directory "dragimagelist" unit1.pas:
Code: Pascal  [Select][+][-]
  1.   protected
  2.     function GetDragImages: TDragImageList; override;
  3.  
  4. function TMyDragObject.GetDragImages: TDragImageList;
  5. begin
  6.   Result := FDragImages;
  7. end;
  8.  


d7_2_laz

  • Full Member
  • ***
  • Posts: 110
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #10 on: April 23, 2021, 12:09:24 pm »
For to make it more easy to communicate, i shrinked down the testcase eeven more to an absolute mininum.

It's a regular treeview now, creating, after MouseDown,  a DragObject at StartDrag, which now simply has an empty square bitmap as dragimage.
At DragOver an Accept is set for the treeview, ....  and at MouseUp being on a node it persists to SIGSEV.

The very simple test case is attached here again.

Is anybody able to throw some light what is wrong, or which requirements possibly have not been met?

dseligo

  • Sr. Member
  • ****
  • Posts: 252
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #11 on: April 23, 2021, 02:53:17 pm »
I've tested a little.
It looks to me that problem surfaces when function TDragImageList.GetDraggingResolution: TDragImageListResolution; returns nil (because property 'Dragging' in Result object is false).

I added 'If Assigned(Self) then' in procedure TDragImageListResolution.HideDragImage; and in procedure TDragImageListResolution.ShowDragImage; and then there was no SIGSEV.

Code: Pascal  [Select][+][-]
  1. procedure TDragImageListResolution.HideDragImage;
  2. begin
  3.   If Assigned(Self) then
  4.   if Dragging then
  5.     TWSDragImageListResolutionClass(WidgetSetClass).HideDragImage(Self, 0, False);
  6. end;
  7.  
  8. procedure TDragImageListResolution.ShowDragImage;
  9. begin
  10.   If Assigned(Self) then
  11.   if Dragging then
  12.     TWSDragImageListResolutionClass(WidgetSetClass).ShowDragImage(Self, 0, 0, 0, False);
  13. end;

I don't know how this works internally, so I am not sure if it is a bug or if you didn't setup bitmap in FDragImages correctly.

P.S.: Check attachment  :)

GetMem

  • Hero Member
  • *****
  • Posts: 4017
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #12 on: April 23, 2021, 03:51:27 pm »
@dseligo
Quote
I don't know how this works internally, so I am not sure if it is a bug or if you didn't setup bitmap in FDragImages correctly.
I do not know either, but the crash should not hapen even if FDragImages is not setup correctly.
In lcl/include/dragimagelist.inc instead of:
Code: Pascal  [Select][+][-]
  1. procedure TDragImageList.HideDragImage;
  2. begin
  3.   GetDraggingResolution.HideDragImage;
  4. end;
we need:
Code: Pascal  [Select][+][-]
  1. procedure TDragImageList.HideDragImage;
  2. var
  3.   DragImageListResolution: TDragImageListResolution;
  4. begin
  5.   DragImageListResolution := GetDraggingResolution;
  6.   if DragImageListResolution <> nil then
  7.     DragImageListResolution.HideDragImage;
  8. end;

Same is true for ShowDragImage.
It has the same effect as your solution 
Code: Pascal  [Select][+][-]
  1. If Assigned(Self) then
but is higher on the chain with one level.
« Last Edit: April 23, 2021, 03:56:16 pm by GetMem »

dseligo

  • Sr. Member
  • ****
  • Posts: 252
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #13 on: April 23, 2021, 04:08:26 pm »
It has the same effect as your solution 
Code: Pascal  [Select][+][-]
  1. If Assigned(Self) then
but is higher on the chain with one level.

I agree, it's better.

GetMem

  • Hero Member
  • *****
  • Posts: 4017
Re: DragDrop ghost image with DragObject; fine, but SIGSEV at Drop - why?
« Reply #14 on: April 23, 2021, 04:48:52 pm »
I applied the changes in r. 65055.

 

TinyPortal © 2005-2018