]> Pileus Git - ~andy/gtk/blob - docs/dnd_internals.txt
stylecontext: Do invalidation on first resize container
[~andy/gtk] / docs / dnd_internals.txt
1 This document describes some of the internals of the DND handling
2 code.
3
4 Organization
5 ============
6
7 The DND code is split between a lowlevel part - gdkdnd.c and a
8 highlevel part - gtkdnd.c.  To put it simply, gdkdnd.c contain the
9 portions of DND code that are easiest to do in raw X, while gtkdnd.c
10 contains the portions of DND that are easiest to do with an event loop
11 and high level selection handling.
12
13 Except for a few details of selection handling, most of the
14 dependencies on the DND protocol are confined to gdkdnd.c.
15 There are two or three supported protocols - Motif DND,
16 Xdnd and a pseudo-protocol ROOTWIN, which is used for drops
17 on root windows that aren't really accepting drops.
18 gdkdnd.c divides into 4 pieces:
19
20  1) Utility functions (finding client windows)
21  2) Motif specific code (the biggest chunk)
22  3) Xdnd specific code
23  4) The public interfaces
24
25 The code in gtkdnd.c roughly consists of three parts  
26   
27  1) General utility functions
28  2) Destination side code
29  3) Source side code.
30
31 Both on the source and dest side, there is some division
32 between the low level layers and the default handlers,
33 though they are rather mixed in many cases.
34
35 Structures and Memory Management
36 ================================
37
38 Information about source sites and drop sites is stored
39 in the structures GtkSourceSite and GtkDestSite.
40
41 Information about in-progress drags and drops is stored
42 in the structures GtkSourceInfo and GtkDestInfo.
43
44 The GtkSourceInfo structure is created when the drag
45 begins, and persists until the drag either completes
46 or times out. A pointer to it is stored in 
47 dataset-data for the GdkDragContext, however there
48 is no ownership. If the SourceInfo is destroyed
49 before the context, the field is simply cleared.
50
51 A GtkDestInfo is attached to each GdkDragContext
52 that is received for an incoming drag. In contrast
53 to the SourceInfo the DestInfo is "owned" by the
54 context, and when the context is destroyed, destroyed.
55
56 The GDK API
57 ===========
58
59 It is expect that the GDK DND API will never be
60 used by anything other than the DND code in GTK+.
61
62 /* Drag and Drop */
63
64 GdkDragContext * gdk_drag_context_new        (void);
65
66 These create and refcount GdkDragContexts in a
67 straightforward manner.
68
69 /* Destination side */
70
71 void             gdk_drag_status        (GdkDragContext   *context,
72                                          GdkDragAction     action,
73                                          guint32           time);
74 void             gdk_drop_reply         (GdkDragContext   *context,
75                                          gboolean          ok,
76                                          guint32           time);
77 void             gdk_drop_finish        (GdkDragContext   *context,
78                                          gboolean          success,
79                                          guint32           time);
80 GdkAtom          gdk_drag_get_selection (GdkDragContext   *context);
81
82 /* Source side */
83
84 GdkDragContext * gdk_drag_begin      (GdkWindow      *window,
85                                       GList          *targets,
86                                       GdkDragAction   actions);
87 gboolean         gdk_drag_get_protocol (guint32          xid,
88                                         GdkDragProtocol *protocol);
89 void             gdk_drag_find_window (GdkDragContext   *context,
90                                        GdkWindow       *drag_window,
91                                        gint             x_root,
92                                        gint             y_root,
93                                        GdkWindow      **dest_window,
94                                        GdkDragProtocol *protocol);
95 gboolean        gdk_drag_motion      (GdkDragContext *context,
96                                       GdkWindow      *dest_window,
97                                       GdkDragProtocol protocol,
98                                       gint            x_root, 
99                                       gint            y_root,
100                                       GdkDragAction   action,
101                                       guint32         time);
102 void            gdk_drag_drop        (GdkDragContext *context,
103                                       guint32         time);
104 void            gdk_drag_abort       (GdkDragContext *context,
105                                       guint32         time);
106
107 GdkAtom       gdk_drag_get_selection (GdkDragContext *context);
108
109 Retrieves the selection that will be used to communicate
110 the data for the drag context (valid on both source
111 and dest sides)
112
113 Cursors and window hierarchies
114 ==============================
115
116 The DND code, when possible (and it isn't possible over
117 Motif window) uses a shaped window as a drag icon.
118 Because the cursor may fall inside this window during the
119 drag, we actually have to figure out which window
120 the cursor is in _ourselves_ so we can ignore the
121 drag icon properly. (Oh for OutputOnly windows!)
122
123 To avoid obscene amounts of server traffic (which are only
124 slightly observable locally, but would really kill a
125 session over a slow link), the code in GDK does
126 XGetWindowAttributes for every child of the root window at
127 the beginning of the drag, then selects with
128 SubstructureNotifyMask on the root window, so that
129 it can update this list.
130
131 It probably would be easier to just reread the entire
132 list when one of these events occurs, instead of 
133 incrementally updating, but updating the list in
134 sync was sort of fun code, so I did it that way ;-)
135
136 There is also a problem of trying to follow the
137 mouse cursor as well as possible. Currently, the
138 code uses PointerMotionHint, and an XQueryPointer
139 on MotionNotify events. This results in pretty
140 good syncing, but may result in somewhat poor
141 accuracy for drops. (Because the coordinates of
142 the drop are the coordinates when the server receives
143 the button press, which might actually be before
144 the XQueryPointer for the previous MotionNotify
145 event is done.)
146
147 Probably better is doing MotionNotify compression 
148 and discarding MotionNotify events when there
149 are more on the queue before the next ButtonPress/Release.
150
151 Proxying
152 ========
153
154 A perhaps rather unusual feature of GTK's DND is proxying. A
155 dest site can be specified as a proxy drop site for another
156 window. This is most needed for the plug-socket code - the
157 socket needs to pass on drags to the plug since the original
158 source only sees toplevel windows. However, it can also be
159 used as a user visible proxy - i.e., dragging to buttons on
160 the taskbar.
161
162 Internally, when the outer drag enters a proxy dest site, a
163 new source drag is created, with SourceInfo and
164 GdkDragContext. From the GDK side, it looks much like a
165 normal source drag; on the GTK+ side, most of the code is
166 disjoint. The need to pass in a specific target window
167 is the reason why the GDK DND API splits
168 gdk_drag_find_window() and gdk_drag_motion().
169
170 For proxy drags, the GtkDestInfo and GtkSourceInfo for the
171 drag point at each other.
172
173 Because the abstraction of the drag protocol is at the GDK
174 level, a proxy drag from Motif to Xdnd or vice versa happens
175 pretty much automatically during the drag, though the
176 drop can get complicated. For Xdnd <-> Motif,
177 Motif <-> Xdnd, or Motif <-> Motif drags, it is necessary to 
178 for the Proxy to retrieve the data and pass it on to
179 the true destination, since either the selection names
180 differ or (Motif<->Motif), the proxy needs to know
181 about the XmDRAG_SUCCESS/FAILURE selection targets.
182
183 Further Reading:
184 ================
185
186 Xdnd:
187
188 The spec is at:
189
190  http://www.cco.caltech.edu/~jafl/xdnd/
191
192 Motif:
193
194 The Motif DND protocol is best described in the 
195 Hungry Programmers _Inside Lesstif_ book, available
196 from:
197
198   http://www.igpm.rwth-aachen.de/~albrecht/hungry.html
199
200 Harald Albrecht and Mitch Miers have done a far
201 better job at documenting the DND protocol then
202 anything the OpenGroup has produced.
203
204
205
206 Owen Taylor
207 otaylor@redhat.com
208 Oct 18, 1998