File: testdnd.ml

package info (click to toggle)
lablgtk3 3.1.5-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 5,796 kB
  • sloc: ml: 40,890; ansic: 22,312; makefile: 133; sh: 17
file content (518 lines) | stat: -rw-r--r-- 21,593 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
(**************************************************************************)
(*    Lablgtk - Examples                                                  *)
(*                                                                        *)
(*    This code is in the public domain.                                  *)
(*    You may freely copy parts of it in your application.                *)
(*                                                                        *)
(**************************************************************************)

(* this is a translation in Caml of the gtk+ example testdnd.c  *)


open Gaux
open Gtk
open GObj

(* GtkThread.start() *)

let _ = GMain.init ()

let drag_icon_xpm = [|
"36 48 9 1";
" 	c None";
".	c #020204";
"+	c #8F8F90";
"@	c #D3D3D2";
"#	c #AEAEAC";
"$	c #ECECEC";
"%	c #A2A2A4";
"&	c #FEFEFC";
"*	c #BEBEBC";
"               .....................";
"              ..&&&&&&&&&&&&&&&&&&&.";
"             ...&&&&&&&&&&&&&&&&&&&.";
"            ..&.&&&&&&&&&&&&&&&&&&&.";
"           ..&&.&&&&&&&&&&&&&&&&&&&.";
"          ..&&&.&&&&&&&&&&&&&&&&&&&.";
"         ..&&&&.&&&&&&&&&&&&&&&&&&&.";
"        ..&&&&&.&&&@&&&&&&&&&&&&&&&.";
"       ..&&&&&&.*$%$+$&&&&&&&&&&&&&.";
"      ..&&&&&&&.%$%$+&&&&&&&&&&&&&&.";
"     ..&&&&&&&&.#&#@$&&&&&&&&&&&&&&.";
"    ..&&&&&&&&&.#$**#$&&&&&&&&&&&&&.";
"   ..&&&&&&&&&&.&@%&%$&&&&&&&&&&&&&.";
"  ..&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.";
" ..&&&&&&&&&&&&.&&&&&&&&&&&&&&&&&&&.";
"................&$@&&&@&&&&&&&&&&&&.";
".&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&&&&&.";
".&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&&&.";
".&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&&&.";
".&&&&&&@#@@$&*@&@#@#$**#$&&&&&&&&&&.";
".&&&&&&&&&&&&&&&&&&&@%&%$&&&&&&&&&&.";
".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.";
".&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&&&.";
".&&&&&&&&&+&$+&$&@&$@&&$@&&&&&&&&&&.";
".&&&&&&&&&+&&#@%#+@#@*$%&+$&&&&&&&&.";
".&&&&&&&&&+&&#@#@&&@*%$%$+&&&&&&&&&.";
".&&&&&&&&&+&$%&#@&#@@#&#@$&&&&&&&&&.";
".&&&&&&&&@#@@$&*@&@#@#$#*#$&&&&&&&&.";
".&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&&&.";
".&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&&&&&.";
".&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&&&&&.";
".&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&&&&&.";
".&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&&&&&.";
".&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&&&&&.";
".&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&&&&&.";
".&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&&&&&.";
".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.";
".&&&&&&&&&&&&&&$#@@$&&&&&&&&&&&&&&&.";
".&&&&&&&&&&&&&&&+&$%&$$@&$@&&$@&&&&.";
".&&&&&&&&&&&&&&&+&&#@%#+@#@*$%$+$&&.";
".&&&&&&&&&&&&&&&+&&#@#@&&@*#$%$+&&&.";
".&&&&&&&&&&&&&&&+&$+&*@&#@@#&#@$&&&.";
".&&&&&&&&&&&&&&$%@@&&*@&@#@#$#*#&&&.";
".&&&&&&&&&&&&&&&&&&&&&&&&&&&$%&%$&&.";
".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.";
".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.";
".&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&.";
"...................................." |]



let trashcan_closed_xpm = [|
"64 80 17 1";
" 	c None";
".	c #030304";
"+	c #5A5A5C";
"@	c #323231";
"#	c #888888";
"$	c #1E1E1F";
"%	c #767677";
"&	c #494949";
"*	c #9E9E9C";
"=	c #111111";
"-	c #3C3C3D";
";	c #6B6B6B";
">	c #949494";
",	c #282828";
"'	c #808080";
")	c #545454";
"!	c #AEAEAC";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                       ==......=$$...===                        ";
"                 ..$------)+++++++++++++@$$...                  ";
"             ..=@@-------&+++++++++++++++++++-....              ";
"          =.$$@@@-&&)++++)-,$$$$=@@&+++++++++++++,..$           ";
"         .$$$$@@&+++++++&$$$@@@@-&,$,-++++++++++;;;&..          ";
"        $$$$,@--&++++++&$$)++++++++-,$&++++++;%%'%%;;$@         ";
"       .-@@-@-&++++++++-@++++++++++++,-++++++;''%;;;%*-$        ";
"       +------++++++++++++++++++++++++++++++;;%%%;;##*!.        ";
"        =+----+++++++++++++++++++++++;;;;;;;;;;;;%'>>).         ";
"         .=)&+++++++++++++++++;;;;;;;;;;;;;;%''>>#>#@.          ";
"          =..=&++++++++++++;;;;;;;;;;;;;%###>>###+%==           ";
"           .&....=-+++++%;;####''''''''''##'%%%)..#.            ";
"           .+-++@....=,+%#####'%%%%%%%%%;@$-@-@*++!.            ";
"           .+-++-+++-&-@$$=$=......$,,,@;&)+!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           =+-++-+++-+++++++++!++++!++++!+++!++!+++=            ";
"            $.++-+++-+++++++++!++++!++++!+++!++!+.$             ";
"              =.++++++++++++++!++++!++++!+++!++.=               ";
"                 $..+++++++++++++++!++++++...$                  ";
"                      $$=.............=$$                       ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                "  |]

let trashcan_open_xpm = [|
"64 80 17 1";
" 	c None";
".	c #030304";
"+	c #5A5A5C";
"@	c #323231";
"#	c #888888";
"$	c #1E1E1F";
"%	c #767677";
"&	c #494949";
"*	c #9E9E9C";
"=	c #111111";
"-	c #3C3C3D";
";	c #6B6B6B";
">	c #949494";
",	c #282828";
"'	c #808080";
")	c #545454";
"!	c #AEAEAC";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                      .=.==.,@                  ";
"                                   ==.,@-&&&)-=                 ";
"                                 .$@,&++;;;%>*-                 ";
"                               $,-+)+++%%;;'#+.                 ";
"                            =---+++++;%%%;%##@.                 ";
"                           @)++++++++;%%%%'#%$                  ";
"                         $&++++++++++;%%;%##@=                  ";
"                       ,-++++)+++++++;;;'#%)                    ";
"                      @+++&&--&)++++;;%'#'-.                    ";
"                    ,&++-@@,,,,-)++;;;'>'+,                     ";
"                  =-++&@$@&&&&-&+;;;%##%+@                      ";
"                =,)+)-,@@&+++++;;;;%##%&@                       ";
"               @--&&,,@&)++++++;;;;'#)@                         ";
"              ---&)-,@)+++++++;;;%''+,                          ";
"            $--&)+&$-+++++++;;;%%'';-                           ";
"           .,-&+++-$&++++++;;;%''%&=                            ";
"          $,-&)++)-@++++++;;%''%),                              ";
"         =,@&)++++&&+++++;%'''+$@&++++++                        ";
"        .$@-++++++++++++;'#';,........=$@&++++                  ";
"       =$@@&)+++++++++++'##-.................=&++               ";
"      .$$@-&)+++++++++;%#+$.....................=)+             ";
"      $$,@-)+++++++++;%;@=........................,+            ";
"     .$$@@-++++++++)-)@=............................            ";
"     $,@---)++++&)@===............................,.            ";
"    $-@---&)))-$$=..............................=)!.            ";
"     --&-&&,,$=,==...........................=&+++!.            ";
"      =,=$..=$+)+++++&@$=.............=$@&+++++!++!.            ";
"           .)-++-+++++++++++++++++++++++++++!++!++!.            ";
"           .+-++-+++++++++++++++++++++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!+++!!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           .+-++-+++-+++++++++!++++!++++!+++!++!++!.            ";
"           =+-++-+++-+++++++++!++++!++++!+++!++!+++=            ";
"            $.++-+++-+++++++++!++++!++++!+++!++!+.$             ";
"              =.++++++++++++++!++++!++++!+++!++.=               ";
"                 $..+++++++++++++++!++++++...$                  ";
"                      $$==...........==$$                       ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                ";
"                                                                "  |]

let window = GWindow.window ~title:"DnD Test" ()
let _ = window#misc#realize ()

let drag_icon =
  GDraw.pixmap_from_xpm_d ~data:drag_icon_xpm ~window ()

let trashcan_open =
  GDraw.pixmap_from_xpm_d ~data:trashcan_open_xpm ~window ()

let trashcan_closed =
  GDraw.pixmap_from_xpm_d ~data:trashcan_closed_xpm ~window ()

let targets = [
  { target = "STRING"; flags = []; info = 0};
  { target = "text/plain"; flags = []; info = 0};
  { target = "text/uri-list"; flags = []; info = 2};
  { target = "application/x-rootwin-drop"; flags = []; info = 1}
]

class drag_handler = object
  method private beginning (_ : drag_context) = ()
  method private data_delete (_ : drag_context) = ()
  method private data_get (_ : drag_context) (_ : selection_context)
      ~(info : int) ~(time : int32) = ()
  method private data_received (_ : drag_context) ~(x : int) ~(y : int)
      (_ : selection_data) ~(info : int) ~(time : int32) = ()
  method private drop (_ : drag_context) ~(x : int) ~(y : int)
      ~(time : int32) = false
  method private ending (_ : drag_context) = ()
  method private leave (_ : drag_context) ~(time : int32) = ()
  method private motion (_ : drag_context) ~(x : int) ~(y : int)
      ~(time : int32) = false
end


class target_drag ?packing ?show () =
  let pixmap = GMisc.pixmap trashcan_closed ?packing ?show () in
object (self)
  inherit widget pixmap#as_widget
  inherit drag_handler
  val mutable have_drag = false

  method leave _ ~time =
    print_endline "leave"; flush stdout;
    have_drag <- false;
    pixmap#set_pixmap trashcan_closed

  method motion context ~x ~y ~time =
    if not have_drag then begin
      have_drag <- true;
      pixmap#set_pixmap trashcan_open
    end;
    let source_typename =
      try
	context#source_widget#misc#get_type
      with Gpointer.Null -> "unknown"
    in
    Printf.printf "motion, source %s\n" source_typename; flush stdout;
    context#status (Some context#suggested_action) ~time;
    true

  method drop context ~x ~y ~time =
    prerr_endline "drop"; flush stdout;
    have_drag <- false;
    pixmap#set_pixmap trashcan_closed;
    match context#targets with
    | [] -> false
    | d :: _ -> pixmap#drag#get_data ~target:d ~time context; true

  method data_received context ~x ~y data ~info ~time =
    if data#format = 8 then begin
      Printf.printf "Received \"%s\" in trashcan\n" data#data;
      flush stdout;
      context#finish ~success:true ~del:false ~time
    end
    else context#finish ~success:false ~del:false ~time

  initializer
    pixmap#drag#dest_set targets ~actions:[`COPY;`MOVE];
    pixmap#drag#connect#leave ~callback:self#leave;
    pixmap#drag#connect#motion ~callback:self#motion;
    pixmap#drag#connect#drop ~callback:self#drop;
    pixmap#drag#connect#data_received ~callback:self#data_received;
    ()
end

class label_drag ?packing ?show () =
  let label = GMisc.label ~text:"Drop Here\n" ?packing ?show () in
object (self)
  inherit widget label#as_widget
  inherit drag_handler
  method data_received context ~x ~y data ~info ~time =
    if data#format = 8 then  begin
      Printf.printf "Received \"%s\" in label\n" data#data;
      flush stdout;
      context#finish ~success:true ~del:false ~time
    end
    else context#finish ~success:false ~del:false ~time

  initializer
    label#drag#dest_set targets ~actions:[`COPY; `MOVE ];
    label#drag#connect#data_received ~callback:self#data_received;
    ()
end

class source_drag ?packing ?show () =
  let button = GButton.button ~label:"Drag Here\n" ?packing ?show () in
object (self)
  inherit widget button#as_widget
  inherit drag_handler
  method data_get _ sel ~info ~time =
    if info = 1 then begin
      print_endline "I was dropped on the rootwin"; flush stdout
    end
    else if info = 2 then
      sel#return "file:///home/otaylor/images/weave.png"
    else
      sel#return "I'm Data!"

  method data_delete _ =
    print_endline "Delete the data!"; flush stdout

  initializer
    button#drag#source_set targets
      ~modi:[`BUTTON1; `BUTTON3 ] ~actions:[`COPY; `MOVE ];
    button#drag#source_set_icon drag_icon;
    button#drag#connect#data_get ~callback:self#data_get;
    button#drag#connect#data_delete ~callback:self#data_delete;
    ()
end

class popup () = object (self)
  inherit drag_handler
  val mutable popup_window = (None : #GWindow.window option)
  val mutable popped_up = false
  val mutable in_popup = false
  val mutable popdown_timer = None
  val mutable popup_timer = None

  method timer = popup_timer
  method remove_timer () =
    may popup_timer
      ~f:(fun pdt -> Timeout.remove pdt; popup_timer <- None)
  method add_timer time ~callback =
    popup_timer <- Some (Timeout.add ~ms:time ~callback)

  method popdown () =
    popdown_timer <- None;
    may popup_window ~f:(fun w -> w#misc#hide ());
    popped_up <- false;
    false

  method motion (_ : drag_context) ~x ~y ~time =
    if not in_popup then begin
      in_popup <- true;
      may popdown_timer ~f:
	begin fun pdt ->
	  print_endline "removed popdown"; flush stdout;
	  Timeout.remove pdt;
	  popdown_timer <- None
	end
    end;
    true

  method leave (_ : drag_context) ~time =
    if in_popup then begin
      in_popup <- false;
      if popdown_timer = None then begin
	print_endline "added popdown"; flush stdout;
	popdown_timer <- Some (Timeout.add ~ms:500 ~callback:self#popdown)
      end
    end

  method popup () =
    if not popped_up then begin
      if popup_window = None then begin
	let w = GWindow.window ~kind:`POPUP ~position:`MOUSE () in
	popup_window <- Some w;
	let table = GPack.table ~rows:3 ~columns:3 ~packing:w#add () in
	for i = 0 to 2 do
	  for j = 0 to 2 do
	    let button =
	      GButton.button ~label:(string_of_int i ^ "," ^ string_of_int j)
		~packing:(table#attach ~left:i ~top:j ~expand:`BOTH) ()
	    in
	    button#drag#dest_set targets ~actions:[`COPY; `MOVE ];
	    button#drag#connect#motion ~callback:self#motion;
	    button#drag#connect#leave ~callback:self#leave;
	  done
	done
      end;
      may popup_window ~f:(fun w -> w#show ());
      popped_up <- true
    end;
    popdown_timer <- Some (Timeout.add ~ms:500 ~callback:self#popdown);
    print_endline "added popdown"; flush stdout;
    self#remove_timer ();
    false
end

class popsite ?packing ?show () =
  let label = GMisc.label ~text:"Popup\n" ?packing ?show ()
  and popup = new popup () in
object (self)
  inherit widget label#as_widget
  inherit drag_handler
  method motion _ ~x ~y ~time =
    if popup#timer = None then begin
      print_endline "added popdown"; flush stdout;
      popup#add_timer 500 ~callback:popup#popup
    end;
    true

  method leave _ ~time =
    popup#remove_timer ()

  initializer
    label#drag#dest_set targets ~actions:[`COPY; `MOVE ];
    label#drag#connect#motion ~callback:self#motion;
    label#drag#connect#leave ~callback:self#leave;
    ()
end

let main () =
  window#connect#destroy ~callback: GMain.quit;
  let table = GPack.table ~rows:2 ~columns:2 ~packing:window#add () in
  let attach = table#attach ~expand:`BOTH in
  new label_drag ~packing:(attach ~left:0 ~top:0) ();
  new target_drag ~packing:(attach ~left:1 ~top:0) ();
  new source_drag ~packing:(attach ~left:0 ~top:1) ();
  new popsite ~packing:(attach ~left:1 ~top:1) ();

  window#show ();
  GMain.main ()

let _ =
  main ()