Discussion:
Checking data format compatibility from OnDragOver
David Barrett-Lennard
2014-09-17 23:29:50 UTC
Permalink
I recently posted the text below to the wxWidgets discussion forum and it
was suggested it be discussed here in order to reach the core developers

David


(first post)

In my use case a window needs to support dropping of data of different
formats at different (x,y) positions. It seems I need
wxDropTarget::OnDragOver to return wxDragNone if and only if the data
source is incompatible (in the sense of an accepted wxDataFormat) at the
given (x,y) position passed to OnDragOver. I cannot see how to do this.

The fact that the acceptable data format is a function of (x,y) suggests I
need to call wxDropTarget::SetDataObject from my implementation of
wxDropTarget::OnDragOver. Is that allowed? In any case the only function I
see that seems to test for data format compatibility is
wxDropTarget::GetData which returns a bool for whether it was successful.
However the documentation says wxDropTarget::GetData can only be called
from wxDropTarget::OnData.

(second post)

I've studied the MS Windows implementation in the version 3.0.0 wxWidgets
source code (see src/msw/ole/droptgt.cpp), and as far as I can tell the
limitation arises with wxWidgets, not from Microsoft. I don't know about
other platforms.

When the mouse enters the window during a drag operation,
wxIDropTarget::DragEnter is called. This is passed an IDataObject (a
Microsoft COM interface) associated with the source. MSWIsAcceptedData is
called on the wxDropTarget, which checks for compatability between the
target wxDataObject (currently set in the wxDropTarget) with the source
IDataObject. The subsequent calls to wxIDropTarget::DragOver do not check
for data format compatibility. Clearly it is assumed the appropriate target
wxDataObject is independent of position.

I don't find that restriction reasonable and I cannot think of a work
around. This is a shame, it means wxWidgets is unsuitable for drag and drop
in my application.

Perhaps it's possible to change wxWidgets to address this shortcoming in a
backwards compatible way. Maybe it should be made possible to call
SetDataObject from OnEnter, OnDragOver, OnDrop or OnData. SetDataObject
currently has a void return type. It could be changed to bool and when it
is called from an OnXXX method it indicates whether the given wxDataObject
is acceptable for the current source IDataObject (which is available in the
member wxDropTarget::m_pIDataSource whenever an OnXXX function is called).
It would be appropriate to initialise wxDropTarget::m_pIDataSource to NULL
in the constructor and to reset it back to NULL when the leave event occurs
(neither of which is done at the moment). That way SetDataObject can work
properly when it's called when no drag operation is in progress. At the
moment the rules on when SetDataObject can or should be called is not
documented and not validated with assertions.
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-09-17 23:40:31 UTC
Permalink
On Wed, 17 Sep 2014 16:29:50 -0700 (PDT) David Barrett-Lennard wrote:

DBL> In my use case a window needs to support dropping of data of different
DBL> formats at different (x,y) positions.

The simplest solution by far would be to use different windows. Is this
really impossible, i.e. do you actually have non-rectangular areas which
must accept data in different formats?

DBL> The fact that the acceptable data format is a function of (x,y) suggests I
DBL> need to call wxDropTarget::SetDataObject from my implementation of
DBL> wxDropTarget::OnDragOver. Is that allowed?

I don't think and it doesn't make much sense to me anyhow. AFAICS what you
want to do should be possible by just using a wxDataObject supporting all
the formats you may potentially accept. All you have to do is to override
OnDragOver() to indicate whether any of them is accepted at the current
position and remember the drop position by overriding OnDrop() or OnData().
You would then stash this drop position into your custom wxDataObject and
it would decide what to return depending on it.

Not very elegant, admittedly, but I don't see anything preventing you from
doing this. Am I missing something?


DBL> When the mouse enters the window during a drag operation,
DBL> wxIDropTarget::DragEnter is called. This is passed an IDataObject (a
DBL> Microsoft COM interface) associated with the source. MSWIsAcceptedData is
DBL> called on the wxDropTarget, which checks for compatability between the
DBL> target wxDataObject (currently set in the wxDropTarget) with the source
DBL> IDataObject. The subsequent calls to wxIDropTarget::DragOver do not check
DBL> for data format compatibility. Clearly it is assumed the appropriate target
DBL> wxDataObject is independent of position.

I think the idea was that doing it on every mouse move would be
prohibitively slow.

DBL> Perhaps it's possible to change wxWidgets to address this shortcoming in a
DBL> backwards compatible way.

Maybe, but let's first see if it isn't already possible using the
workaround above. If it is, I'd rather avoid complicating these classes
even further, they're already not that obvious to understand.

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
David Barrett-Lennard
2014-09-18 01:22:09 UTC
Permalink
Post by Vadim Zeitlin
DBL> In my use case a window needs to support dropping of data of different
DBL> formats at different (x,y) positions.
The simplest solution by far would be to use different windows. Is this
really impossible, i.e. do you actually have non-rectangular areas which
must accept data in different formats?
I've developed an entire GUI framework that uses OpenGL to render
everything under a single wxGLCanvas.
Post by Vadim Zeitlin
DBL> The fact that the acceptable data format is a function of (x,y) suggests I
DBL> need to call wxDropTarget::SetDataObject from my implementation of
DBL> wxDropTarget::OnDragOver. Is that allowed?
I don't think and it doesn't make much sense to me anyhow. AFAICS what you
want to do should be possible by just using a wxDataObject supporting all
the formats you may potentially accept.
That would complicate and probably impose limitations on my GUI framework.
E.g. *during *a drag and drop operation, for some other unrelated reason a
DLL could be loaded and a new drop target for a new kind of data format
appears within some region under the wxGLCanvas. With some difficulty I
could arrange for a wxDataObject to change the set of formats it accepts
over time, but I don't think the wxWidgets implementation of DnD can handle
that.
Post by Vadim Zeitlin
All you have to do is to override
OnDragOver() to indicate whether any of them is accepted at the current
position and remember the drop position by overriding OnDrop() or OnData().
You would then stash this drop position into your custom wxDataObject and
it would decide what to return depending on it.
Not very elegant, admittedly, but I don't see anything preventing you from
doing this. Am I missing something?
I don't see how OnDragOver() can get any information about the source. The
wxWidgets doco says GetData() may only be called from OnData() which makes
sense (it doesn't seem reasonable to copy the data from the data source to
the target data object at the rate of mouse move events). At the time
OnDragOver() is called wxDropTarget::m_dataObject doesn't have any
information about the source.

When the mouse enters the window wxDropTarget::MSWIsAcceptedData() is
called which ends up calling m_dataObject->GetAllFormats(), but no
information is put into m_dataObject. The format returned
by wxDropTarget::MSWGetSupportedFormat() isn't recorded anywhere.

bool wxDropTarget::MSWIsAcceptedData(IDataObject *pIDataSource) const
{
return MSWGetSupportedFormat(pIDataSource) != wxDF_INVALID;
}

The method wxDropTarget::GetMatchingPair() seems useful but it appears to
be undocumented and platform specific.
Post by Vadim Zeitlin
DBL> When the mouse enters the window during a drag operation,
DBL> wxIDropTarget::DragEnter is called. This is passed an IDataObject (a
DBL> Microsoft COM interface) associated with the source.
MSWIsAcceptedData is
DBL> called on the wxDropTarget, which checks for compatability between the
DBL> target wxDataObject (currently set in the wxDropTarget) with the source
DBL> IDataObject. The subsequent calls to wxIDropTarget::DragOver do not check
DBL> for data format compatibility. Clearly it is assumed the appropriate target
DBL> wxDataObject is independent of position.
I think the idea was that doing it on every mouse move would be
prohibitively slow.
I'd be surprised if data format testing would take anything like 20msec,
but in any case for each mouse move event an application can perform hit
testing to work out what format/type of target data object is appropriate
at the (x,y) position, and only call SetDataObject() when it needs to
*change*. So I'm thinking it's ok for SetDataObject() to call
MSWIsAcceptedData() even if the latter happens to be expensive.
Post by Vadim Zeitlin
DBL> Perhaps it's possible to change wxWidgets to address this shortcoming in a
DBL> backwards compatible way.
Maybe, but let's first see if it isn't already possible using the
workaround above. If it is, I'd rather avoid complicating these classes
even further, they're already not that obvious to understand.
Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Eric Jensen
2014-09-18 01:40:37 UTC
Permalink
Hello David,

Thursday, September 18, 2014, 3:22:09 AM, you wrote:

DBL> On Thursday, September 18, 2014 7:40:44 AM UTC+8, Vadim Zeitlin wrote:
DBL> On Wed, 17 Sep 2014 16:29:50 -0700 (PDT) David Barrett-Lennard wrote:
DBL>
DBL>> In my use case a window needs to support dropping of data of different
DBL>> formats at different (x,y) positions.
DBL>
DBL> The simplest solution by far would be to use different windows. Is this
DBL> really impossible, i.e. do you actually have non-rectangular areas which
DBL> must accept data in different formats?



DBL> I've developed an entire GUI framework that uses OpenGL to
DBL> render everything under a single wxGLCanvas.
DBL>

Do you only have to drag-and-drop inside your own application? In that
case it's probably easier to ignore the whole wxWidgets DnD stuff and
implement it yourself. Should be relatively simple.

Eric
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
David Barrett-Lennard
2014-09-18 07:28:32 UTC
Permalink
Post by Eric Jensen
Hello David,
DBL>
DBL>> In my use case a window needs to support dropping of data of different
DBL>> formats at different (x,y) positions.
DBL>
DBL> The simplest solution by far would be to use different windows. Is this
DBL> really impossible, i.e. do you actually have non-rectangular areas which
DBL> must accept data in different formats?
DBL> I've developed an entire GUI framework that uses OpenGL to
DBL> render everything under a single wxGLCanvas.
DBL>
Do you only have to drag-and-drop inside your own application? In that
case it's probably easier to ignore the whole wxWidgets DnD stuff and
implement it yourself. Should be relatively simple.
Yes, that might be what I'll have to do.

By the way the issue affects other developers. Typing "drag and drop" into
the search facility of google groups for this group and quickly eye balling
the results shows me at least two other posters with the same issue:

https://groups.google.com/forum/?hl=en&fromgroups#!searchin/wx-users/drag$20drop/wx-users/8yqMw7f9FB8/LRLG8O3odTEJ
https://groups.google.com/forum/?hl=en&fromgroups#!searchin/wx-users/drag$20drop/wx-users/Krp_aj8DLxc/-RjTlIabRAsJ

(and there are surely more developers with the issue that find workarounds
that you don't hear about - particularly the imperfect solution which is to
define a wxDataObject that accepts all potential formats and the user only
finds out whether it works when the mouse button is released).

David
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-09-18 11:49:57 UTC
Permalink
On Wed, 17 Sep 2014 18:22:09 -0700 (PDT) David Barrett-Lennard wrote:

DBL> > I don't think and it doesn't make much sense to me anyhow. AFAICS what
DBL> > you want to do should be possible by just using a wxDataObject
DBL> > supporting all the formats you may potentially accept.
DBL>
DBL> That would complicate and probably impose limitations on my GUI framework.
DBL> E.g. *during *a drag and drop operation, for some other unrelated reason a
DBL> DLL could be loaded and a new drop target for a new kind of data format
DBL> appears within some region under the wxGLCanvas.

I have trouble convincing myself that this is a realistic problem...

DBL> I don't see how OnDragOver() can get any information about the source.

Yes, you're right, some method of retrieving the formats supported by the
data being actually dragged would be needed. This should be relatively
straightforward to implement under MSW, but I'm less sure about the other
platforms.

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
David Barrett-Lennard
2014-09-18 15:46:47 UTC
Permalink
Post by Vadim Zeitlin
DBL> > I don't think and it doesn't make much sense to me anyhow. AFAICS what
DBL> > you want to do should be possible by just using a wxDataObject
DBL> > supporting all the formats you may potentially accept.
DBL>
DBL> That would complicate and probably impose limitations on my GUI framework.
DBL> E.g. *during *a drag and drop operation, for some other unrelated reason a
DBL> DLL could be loaded and a new drop target for a new kind of data format
DBL> appears within some region under the wxGLCanvas.
I have trouble convincing myself that this is a realistic problem...
Are you willing to assure me that replacing/modifying the target
wxDataObject *during *a drag and drop (which seems to fall outside the
normal, expected usage) will not do something unfortunate like crash the
process in some version now or in the future on some platform?

David
Post by Vadim Zeitlin
DBL> I don't see how OnDragOver() can get any information about the source.
Yes, you're right, some method of retrieving the formats supported by the
data being actually dragged would be needed. This should be relatively
straightforward to implement under MSW, but I'm less sure about the other
platforms.
Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-09-19 14:11:22 UTC
Permalink
On Thu, 18 Sep 2014 08:46:47 -0700 (PDT) David Barrett-Lennard wrote:

DBL> On Thursday, September 18, 2014 7:50:07 PM UTC+8, Vadim Zeitlin wrote:
DBL> >
DBL> > On Wed, 17 Sep 2014 18:22:09 -0700 (PDT) David Barrett-Lennard wrote:
DBL> >
DBL> > DBL> > I don't think and it doesn't make much sense to me anyhow. AFAICS
DBL> > what
DBL> > DBL> > you want to do should be possible by just using a wxDataObject
DBL> > DBL> > supporting all the formats you may potentially accept.
DBL> > DBL>
DBL> > DBL> That would complicate and probably impose limitations on my GUI
DBL> > framework.
DBL> > DBL> E.g. *during *a drag and drop operation, for some other unrelated
DBL> > reason a
DBL> > DBL> DLL could be loaded and a new drop target for a new kind of data
DBL> > format
DBL> > DBL> appears within some region under the wxGLCanvas.
DBL> >
DBL> > I have trouble convincing myself that this is a realistic problem...

Just to make it clear: what I meant was that starting to dynamically
support new formats during a dnd operation was so esoteric that I really
didn't want to do anything special to support it.

DBL> Are you willing to assure me that replacing/modifying the target
DBL> wxDataObject *during *a drag and drop (which seems to fall outside the
DBL> normal, expected usage) will not do something unfortunate like crash the
DBL> process in some version now or in the future on some platform?

Of course I can't assure you, I'm not even sure if it works right now...

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
David Barrett-Lennard
2014-09-19 15:47:17 UTC
Permalink
Post by Vadim Zeitlin
DBL> >
DBL> >
DBL> > DBL> > I don't think and it doesn't make much sense to me anyhow. AFAICS
DBL> > what
DBL> > DBL> > you want to do should be possible by just using a wxDataObject
DBL> > DBL> > supporting all the formats you may potentially accept.
DBL> > DBL>
DBL> > DBL> That would complicate and probably impose limitations on my GUI
DBL> > framework.
DBL> > DBL> E.g. *during *a drag and drop operation, for some other unrelated
DBL> > reason a
DBL> > DBL> DLL could be loaded and a new drop target for a new kind of data
DBL> > format
DBL> > DBL> appears within some region under the wxGLCanvas.
DBL> >
DBL> > I have trouble convincing myself that this is a realistic problem...
Just to make it clear: what I meant was that starting to dynamically
support new formats during a dnd operation was so esoteric that I really
didn't want to do anything special to support it.
DBL> Are you willing to assure me that replacing/modifying the target
DBL> wxDataObject *during *a drag and drop (which seems to fall outside the
DBL> normal, expected usage) will not do something unfortunate like crash the
DBL> process in some version now or in the future on some platform?
Of course I can't assure you, I'm not even sure if it works right now...
My point was that it's not clear whether one can safely replace/modify the
target wxDataObject at any time once the associated window is up and
processing mouse events. Therefore it seems appropriate to assume the
accepted formats cannot vary with time (just as they cannot vary with
position).

I meant it would be restrictive to be forced to support all potential data
formats from the time the window is first created.

David
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Vadim Zeitlin
2014-09-19 15:53:05 UTC
Permalink
On Fri, 19 Sep 2014 08:47:17 -0700 (PDT) David Barrett-Lennard wrote:

DBL> My point was that it's not clear whether one can safely replace/modify the
DBL> target wxDataObject at any time once the associated window is up and
DBL> processing mouse events. Therefore it seems appropriate to assume the
DBL> accepted formats cannot vary with time (just as they cannot vary with
DBL> position).

I am not sure about this but this can well be true.

DBL> I meant it would be restrictive to be forced to support all potential data
DBL> formats from the time the window is first created.

Sorry, I really don't see it as being very restrictive at all. At most, I
could see how you'd wish to postpone initializing dnd support until it
actually happened the first time to make the program startup faster. But
beyond this it doesn't look like a real problem in practice to me.

Again, this is not to say that you shouldn't try to improve this if this
is important to you.

Regards,
VZ
--
TT-Solutions: wxWidgets consultancy and technical support
http://www.tt-solutions.com/
David Barrett-Lennard
2014-09-19 17:15:23 UTC
Permalink
Post by Vadim Zeitlin
DBL> My point was that it's not clear whether one can safely
replace/modify the
DBL> target wxDataObject at any time once the associated window is up and
DBL> processing mouse events. Therefore it seems appropriate to assume the
DBL> accepted formats cannot vary with time (just as they cannot vary with
DBL> position).
I am not sure about this but this can well be true.
DBL> I meant it would be restrictive to be forced to support all potential data
DBL> formats from the time the window is first created.
Sorry, I really don't see it as being very restrictive at all. At most, I
could see how you'd wish to postpone initializing dnd support until it
actually happened the first time to make the program startup faster. But
beyond this it doesn't look like a real problem in practice to me.
I support a component architecture and loading of DLLs on demand, which for
example would be appropriate for plugins and linking and embedding and so
forth, and obviously I need plugins to be able to define data formats. I'm
not going to force every possible plugin to be loaded at start up, whether
it's needed or not.

David
--
Please read http://www.wxwidgets.org/support/mlhowto.htm before posting.

To unsubscribe, send email to wx-users+***@googlegroups.com
or visit http://groups.google.com/group/wx-users
Loading...