Closed Bug 121251 Opened 23 years ago Closed 22 years ago

gtk2 needs drag and drop

Categories

(Core :: DOM: Copy & Paste and Drag & Drop, defect)

x86
Linux
defect
Not set
normal

Tracking

()

RESOLVED FIXED

People

(Reporter: blizzard, Assigned: blizzard)

References

Details

Attachments

(2 files, 2 obsolete files)

The gtk2 port needs drag and drop done. Need to figure out if we can share any of the code with the gtk1.2 code - there's a lot there.
Blocks: gtk2
*** Bug 146374 has been marked as a duplicate of this bug. ***
Mozilla also does not drag and drop correctly to and from KDE3/QT3. Mozilla is an isolated application on the modern desktop.
Hi, Chris I want to work on this bug and below is my investigation in DND. If there is any error, please tell me. Your guidance will make this work better. 1. Difference of DND between gtk1.2 and gtk2.0: Gtk2 includes all the DND interfaces defined in gtk1.2( the declarations of interface are identical). Additionally, gtk2 includes 8 new interfaces, all of which provide new (but nonsignificant) functions. All new interfaces don't intervene existing interfaces. So we can use all the code in widget/src/gtk/nsDragService.cpp(h) without modificaiton. (Testing demonstrates that adding "nsDragService.cpp/h" to widget/src/gtk2 has no compiling error) . 2. To Do Such work is not enough because DND doesn't like CCP(cut, copy&paste). All CCP implementation locates in nsClipboard.cpp(h) which provide interfaces just like providing service. CCP's implementation has no relation to individual widget. But DND's operation concern every widget because any widget may be DND source and DND destination. So widget must deal with DND signal such as "drag_motion", "drag_leave", "drag_drop", "drag_data_received". "widget/src/gtk/nsWidget.cpp(h) & nsWindow.cpp(h) has a lot of code dealing with DND, but the counterpart at "widget/src/gtk2" has no such code. So next step is writing DND code in widget implementation at "widget/src/gtk2".
The biggest difference will be how the target of the drag is determined. In the old code, there was a lot of X hackery that was used to determine exactly which window was the target of the drag. Because Mozilla in this case is a real Gtk widget, we can use the standard signals and the window target of the drag to get the real target. So, basically, the code is greatly simplified. As for the nsDragService code, I think that there's a lot of opportunity to clean it up. It probably doesn't need to be as complicated as it was because the gtk interfaces are so much cleaner.
Hi, Chris Now, Jeff and I are doing DND work. I am going to implement the DND function for mozilla widget. These days I am looking into "DND" part of gtk1.2 widget implementation and "EVENT HANDLE" part of gtk2 widget implementation. I want to follow the way below. Please point out if there is any mistaken, thanks a lot. ---------------------------------------------------------------------- In "widget/src/gtk", nsWindow handle 4 DND signal "drag_motion", "drag_leave", "drag_drop", "drag_data_received". These signals are bound to "mShell", which means these signals are captured by nsWindow where events don't really happen. After nsWindow who has "mShell" got the event, it look for the innermost nsWindow for the event (that is nsWindow where event really happen), generate nsMouseEvent(type="NS_DRAGDROP_EVENT") and forward it to the innermost nsWindow. When looking for innermost nsWindow, it use a lot of Xlib functions. In "widget/src/gtk2", signal is bound to "mContainer". After nsWindow who as "mContainer" got the event, it get the gdkwindow where event happens from "event->window", then through "g_object_get_data(G_OBJECT(window), "nsWindow")" found the "innermost" nsWindow. It's much simpler than "widget/src/gtk" because its better structure of nsWindow. TODO So, all the things to do is to find proper nsWindow to handle the event, where "widget/src/gtk" and "widget/src/gtk2" going different way. For DND, I need to bind 4 DND signal "drag_motion", "drag_leave", "drag_drop", "drag_data_received" to "mContainer" just like "button_press_event" or "button_release_event". Then in handler, find the proper nsWindow to handle DND signal.
That sounds pretty reasonable. You need to attach the right signals to the container, which it sounds like you understand, and then translate the signals to the right inner nsWindow. I haven't looked at it personally, but it appears that the x/y coordinates of the drag event are still always relative to the container, not a possible inner window. This means that we still need to do some translation from the outer window location to the inner window x/y to deliver the Mozilla event. Please don't use the Xlib code that's in the current gtk 1.2 code. It should be relatively easy to walk the children and siblings to get the correct coordinates. But all in all, that looks OK. Here's a tip. I think that you might be able to hook up to the drag_end signal on the source side to catch the end of the drag. You might be able to part of the inner loop bits that way.
CURRENT PROBLEM: Chris, I can't find the right inner nsWindow when Drag and Drop. When other events happen such as "button_press", I can get gdk window throgh CALLBACK function, then get the corresponding nsWindow. But all the CALLBACK functions of DND don't provide GdkEvent, so I can't get gdk window. DND CALLBACK function returns "GdkDragContext", which contains source window and destination window(gdkwindow) of the current drag. Because when setting possible drag dest, only the mContainer is set(mContainer is a GtkWidget, mDrawingarea is not). So we always get mContainer's gdkwindow through GdkDragContext's dest window. That is to say, I can't get the right inner nsWindow through the information DND CALLBACK functions provide. SUBSTITUE SOLUTION: I use Xlib to get the right inner nsWindow as gtk1.2 does instead, [GTK2] DND works well. Now the only thing left is to find how to get the right inner nsWindow without using Xlib. Chris, do you have any good idea? Thanks.
> That is to say, I can't get the right inner nsWindow through the information > DND CALLBACK functions provide. That's exactly what I was saying. Instead of using the Xlib functions provided, you can walk the list of children of the window (this is available in the nsIWidget interface) and find the inner target.
Attached patch first working patch of gtk2 drag&drop (obsolete) (deleted) — Splinter Review
This is a testing patch of gtk2 DND. It use xlib to locate the right inner nsWindow because the children list of nsWindow is not complete, and the right inner nsWindow can't be found through "GetChildren" of nsIWidget. The detail description of the current problem is in the next attachment.
Why don't you use the children at the gdk level? gdk_window_peek_children() and friends. That doesn't require X roundtrips and it should contain all the information you need.
Locating the right inner nsWindow means walking the tree of window(gdkwindow or xwindow) looking for which child window who matches the coords. But several windows may match the corrds at the same time. So, the top one (up in z-order) should be chosen. This siutation happens when browser has several tabs. All tab's windows lap over and only one is at the top. This means when locating the right inner window, the same input of "GetInnerMostWindow" (the outer window and the coords) may have different output(the right inner window) due to the different current top window. The tree of gdkwindow was created when generating gdk window and won't change afterward. Only the tree of xwindow can response the change. So gdkwindow tree can't be used to locating the rigth inner window. My testing demonstrate this. Using xlib is a feasible(maybe only) way. Another Question(about Xlib): The children "XQueryTree" return are listed in current stacking order, from bottommost (first) to topmost (last). But the code of gtk ("GetInnerMostWindow") search from bottommost to topmost(first to last), when the top one should be searched first. I am confused why this works well. The same function won't work in "gtk2" (that's what I expected :-)), changing to "search from topmost to bottommost" fix the problem. But then, the DND of composer can't find the target window when dragging. Further investigation found that the user selected tab's window of composer is not at the top of xwindow tree. "GetInnerMostWindow" didn't return the right inner window. Now, I am really confused by all these question: 1. why gtk DND of brower & composer works normally when "GetInnerMostWindow" search from bottommost to topmost in the xwindow tree. 2. why gtk2 DND of composer won't work while DND of browser works well. The patch use the original "GetInnerMostWindow" of gtk, which make the DND of browser don't work well when several tabs exist. But the content can be dragged into composer. I can't figure out the reason because it seems not to do with DND.
I think I can answer part of the problem of COMMENT#12 now. Finding which is the right inner window should use z-order and judge whether it's visible. Adding "visible" judgement in "GetInnerMostWindow" has fixed the problem. I don't know if it's sufficient only to judge "visible".If answer is "YES", walking the gdk window tree is perfect to locating the right inner window. My Demo walking gdkwindow tree without z-order info seems to say it's "YES", but I don't know if it fits all case.
I was going to suggest that you check the visibility on the gdk window, to tell which windows were hidden.
Attached patch the second working patch (no xlib function) (obsolete) (deleted) — Splinter Review
This patch locates the right inner window walking through gdkwindow tree and judge the "visibility" instead of using xlib function.
This patch make coding style better than the old one. And make changes: 1. Add "check the number of iteration" in nsDragService::GetTargetDragData 2. Move "record the last gdk event time"(so don't touch nsCommonWidget.h/cpp)
Attachment #89913 - Attachment is obsolete: true
Attachment #90483 - Attachment is obsolete: true
I made a couple of minor changes and checked this in. I removed the #ifdefs around the LOG() statements since we want those built for debugging. I also made a couple of minor string changes because a couple of interfaces changed since the patch was made. Yay, marking FIXED!
Status: NEW → RESOLVED
Closed: 23 years ago
Resolution: --- → FIXED
it looks like nsDragService.h and nsDragService.cpp were not cvs added.
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Woops (*blush*).
Status: REOPENED → RESOLVED
Closed: 23 years ago22 years ago
Resolution: --- → FIXED
Thank Chris for reveiwing and checking in the patch! also for all the nights you spend to chat with us! Wish to see you on IRC again :-)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Creator:
Created:
Updated:
Size: