]> Pileus Git - ~andy/gtk/blob - gdk/gdkoffscreenwindow.c
gdk: gdk_drawable_get_display() => gdk_window_get_display()
[~andy/gtk] / gdk / gdkoffscreenwindow.c
1 /* GDK - The GIMP Drawing Kit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19
20 /*
21  * Modified by the GTK+ Team and others 1997-2005.  See the AUTHORS
22  * file for a list of people on the GTK+ Team.  See the ChangeLog
23  * files for a list of changes.  These files are distributed with
24  * GTK+ at ftp://ftp.gtk.org/pub/gtk/.
25  */
26
27 #include <config.h>
28 #include <math.h>
29 #include "gdk.h"
30 #include "gdkwindow.h"
31 #include "gdkinternals.h"
32 #include "gdkwindowimpl.h"
33 #include "gdkdrawable.h"
34 #include "gdktypes.h"
35 #include "gdkscreen.h"
36 #include "gdkcolor.h"
37
38
39 /* LIMITATIONS:
40  *
41  * Offscreen windows can't be the child of a foreign window,
42  *   nor contain foreign windows
43  * GDK_POINTER_MOTION_HINT_MASK isn't effective
44  */
45
46 typedef struct _GdkOffscreenWindow      GdkOffscreenWindow;
47 typedef struct _GdkOffscreenWindowClass GdkOffscreenWindowClass;
48
49 struct _GdkOffscreenWindow
50 {
51   GdkDrawable parent_instance;
52
53   GdkWindow *wrapper;
54   GdkColormap *colormap;
55   GdkScreen *screen;
56
57   cairo_surface_t *surface;
58   GdkWindow *embedder;
59 };
60
61 struct _GdkOffscreenWindowClass
62 {
63   GdkDrawableClass parent_class;
64 };
65
66 #define GDK_TYPE_OFFSCREEN_WINDOW            (gdk_offscreen_window_get_type())
67 #define GDK_OFFSCREEN_WINDOW(object)         (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindow))
68 #define GDK_IS_OFFSCREEN_WINDOW(object)      (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_OFFSCREEN_WINDOW))
69 #define GDK_OFFSCREEN_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
70 #define GDK_IS_OFFSCREEN_WINDOW_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_OFFSCREEN_WINDOW))
71 #define GDK_OFFSCREEN_WINDOW_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_OFFSCREEN_WINDOW, GdkOffscreenWindowClass))
72
73 static void       gdk_offscreen_window_impl_iface_init    (GdkWindowImplIface         *iface);
74 static void       gdk_offscreen_window_hide               (GdkWindow                  *window);
75
76 G_DEFINE_TYPE_WITH_CODE (GdkOffscreenWindow,
77                          gdk_offscreen_window,
78                          GDK_TYPE_DRAWABLE,
79                          G_IMPLEMENT_INTERFACE (GDK_TYPE_WINDOW_IMPL,
80                                                 gdk_offscreen_window_impl_iface_init));
81
82
83 static void
84 gdk_offscreen_window_finalize (GObject *object)
85 {
86   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (object);
87
88   cairo_surface_destroy (offscreen->surface);
89
90   G_OBJECT_CLASS (gdk_offscreen_window_parent_class)->finalize (object);
91 }
92
93 static void
94 gdk_offscreen_window_init (GdkOffscreenWindow *window)
95 {
96 }
97
98 static void
99 gdk_offscreen_window_destroy (GdkWindow *window,
100                               gboolean   recursing,
101                               gboolean   foreign_destroy)
102 {
103   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
104   GdkOffscreenWindow *offscreen;
105
106   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
107
108   gdk_offscreen_window_set_embedder (window, NULL);
109   
110   if (!recursing)
111     gdk_offscreen_window_hide (window);
112
113   g_object_unref (offscreen->colormap);
114   offscreen->colormap = NULL;
115 }
116
117 static gboolean
118 is_parent_of (GdkWindow *parent,
119               GdkWindow *child)
120 {
121   GdkWindow *w;
122
123   w = child;
124   while (w != NULL)
125     {
126       if (w == parent)
127         return TRUE;
128
129       w = gdk_window_get_parent (w);
130     }
131
132   return FALSE;
133 }
134
135 static cairo_surface_t *
136 gdk_offscreen_window_ref_cairo_surface (GdkDrawable *drawable)
137 {
138   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
139
140   return cairo_surface_reference (offscreen->surface);
141 }
142
143 static GdkColormap*
144 gdk_offscreen_window_get_colormap (GdkDrawable *drawable)
145 {
146   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (drawable);
147
148   return offscreen->colormap;
149 }
150
151 void
152 _gdk_offscreen_window_new (GdkWindow     *window,
153                            GdkScreen     *screen,
154                            GdkWindowAttr *attributes,
155                            gint           attributes_mask)
156 {
157   GdkWindowObject *private;
158   GdkOffscreenWindow *offscreen;
159
160   g_return_if_fail (attributes != NULL);
161
162   if (attributes->wclass != GDK_INPUT_OUTPUT)
163     return; /* Can't support input only offscreens */
164
165   private = (GdkWindowObject *)window;
166
167   if (private->parent != NULL && GDK_WINDOW_DESTROYED (private->parent))
168     return;
169
170   private->impl = g_object_new (GDK_TYPE_OFFSCREEN_WINDOW, NULL);
171   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
172   offscreen->wrapper = window;
173
174   offscreen->screen = screen;
175
176   if (attributes_mask & GDK_WA_COLORMAP)
177     offscreen->colormap = g_object_ref (attributes->colormap);
178   else
179     {
180       if (gdk_screen_get_system_visual (screen) == private->visual)
181         {
182           offscreen->colormap = gdk_screen_get_system_colormap (screen);
183           g_object_ref (offscreen->colormap);
184         }
185       else
186         offscreen->colormap = gdk_colormap_new (private->visual, FALSE);
187     }
188
189   offscreen->surface = gdk_window_create_similar_surface ((GdkWindow *)private->parent,
190                                                           CAIRO_CONTENT_COLOR,
191                                                           private->width,
192                                                           private->height);
193 }
194
195 static gboolean
196 gdk_offscreen_window_reparent (GdkWindow *window,
197                                GdkWindow *new_parent,
198                                gint       x,
199                                gint       y)
200 {
201   GdkWindowObject *private = (GdkWindowObject *)window;
202   GdkWindowObject *new_parent_private = (GdkWindowObject *)new_parent;
203   GdkWindowObject *old_parent;
204   gboolean was_mapped;
205
206   if (new_parent)
207     {
208       /* No input-output children of input-only windows */
209       if (new_parent_private->input_only && !private->input_only)
210         return FALSE;
211
212       /* Don't create loops in hierarchy */
213       if (is_parent_of (window, new_parent))
214         return FALSE;
215     }
216
217   was_mapped = GDK_WINDOW_IS_MAPPED (window);
218
219   gdk_window_hide (window);
220
221   if (private->parent)
222     private->parent->children = g_list_remove (private->parent->children, window);
223
224   old_parent = private->parent;
225   private->parent = new_parent_private;
226   private->x = x;
227   private->y = y;
228
229   if (new_parent_private)
230     private->parent->children = g_list_prepend (private->parent->children, window);
231
232   _gdk_synthesize_crossing_events_for_geometry_change (window);
233   if (old_parent)
234     _gdk_synthesize_crossing_events_for_geometry_change (GDK_WINDOW (old_parent));
235
236   return was_mapped;
237 }
238
239 static void
240 from_embedder (GdkWindow *window,
241                double embedder_x, double embedder_y,
242                double *offscreen_x, double *offscreen_y)
243 {
244   GdkWindowObject *private;
245
246   private = (GdkWindowObject *)window;
247
248   g_signal_emit_by_name (private->impl_window,
249                          "from-embedder",
250                          embedder_x, embedder_y,
251                          offscreen_x, offscreen_y,
252                          NULL);
253 }
254
255 static void
256 to_embedder (GdkWindow *window,
257              double offscreen_x, double offscreen_y,
258              double *embedder_x, double *embedder_y)
259 {
260   GdkWindowObject *private;
261
262   private = (GdkWindowObject *)window;
263
264   g_signal_emit_by_name (private->impl_window,
265                          "to-embedder",
266                          offscreen_x, offscreen_y,
267                          embedder_x, embedder_y,
268                          NULL);
269 }
270
271 static gint
272 gdk_offscreen_window_get_root_coords (GdkWindow *window,
273                                       gint       x,
274                                       gint       y,
275                                       gint      *root_x,
276                                       gint      *root_y)
277 {
278   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
279   GdkOffscreenWindow *offscreen;
280   int tmpx, tmpy;
281
282   tmpx = x;
283   tmpy = y;
284
285   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
286   if (offscreen->embedder)
287     {
288       double dx, dy;
289       to_embedder (window,
290                    x, y,
291                    &dx, &dy);
292       tmpx = floor (dx + 0.5);
293       tmpy = floor (dy + 0.5);
294       gdk_window_get_root_coords (offscreen->embedder,
295                                   tmpx, tmpy,
296                                   &tmpx, &tmpy);
297
298     }
299
300   if (root_x)
301     *root_x = tmpx;
302   if (root_y)
303     *root_y = tmpy;
304
305   return TRUE;
306 }
307
308 static gboolean
309 gdk_offscreen_window_get_device_state (GdkWindow       *window,
310                                        GdkDevice       *device,
311                                        gint            *x,
312                                        gint            *y,
313                                        GdkModifierType *mask)
314 {
315   GdkWindowObject *private = GDK_WINDOW_OBJECT (window);
316   GdkOffscreenWindow *offscreen;
317   int tmpx, tmpy;
318   double dtmpx, dtmpy;
319   GdkModifierType tmpmask;
320
321   tmpx = 0;
322   tmpy = 0;
323   tmpmask = 0;
324
325   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
326   if (offscreen->embedder != NULL)
327     {
328       gdk_window_get_device_position (offscreen->embedder, device, &tmpx, &tmpy, &tmpmask);
329       from_embedder (window,
330                      tmpx, tmpy,
331                      &dtmpx, &dtmpy);
332       tmpx = floor (dtmpx + 0.5);
333       tmpy = floor (dtmpy + 0.5);
334     }
335
336   if (x)
337     *x = tmpx;
338   if (y)
339     *y = tmpy;
340   if (mask)
341     *mask = tmpmask;
342   return TRUE;
343 }
344
345 /**
346  * gdk_offscreen_window_get_surface:
347  * @window: a #GdkWindow
348  *
349  * Gets the offscreen surface that an offscreen window renders into.
350  * If you need to keep this around over window resizes, you need to
351  * add a reference to it.
352  *
353  * Returns: The offscreen surface, or %NULL if not offscreen
354  */
355 cairo_surface_t *
356 gdk_offscreen_window_get_surface (GdkWindow *window)
357 {
358   GdkWindowObject *private = (GdkWindowObject *)window;
359   GdkOffscreenWindow *offscreen;
360
361   g_return_val_if_fail (GDK_IS_WINDOW (window), FALSE);
362
363   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
364     return NULL;
365
366   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
367   return offscreen->surface;
368 }
369
370 static void
371 gdk_offscreen_window_raise (GdkWindow *window)
372 {
373   /* gdk_window_raise already changed the stacking order */
374   _gdk_synthesize_crossing_events_for_geometry_change (window);
375 }
376
377 static void
378 gdk_offscreen_window_lower (GdkWindow *window)
379 {
380   /* gdk_window_lower already changed the stacking order */
381   _gdk_synthesize_crossing_events_for_geometry_change (window);
382 }
383
384 static void
385 gdk_offscreen_window_move_resize_internal (GdkWindow *window,
386                                            gint       x,
387                                            gint       y,
388                                            gint       width,
389                                            gint       height,
390                                            gboolean   send_expose_events)
391 {
392   GdkWindowObject *private = (GdkWindowObject *)window;
393   GdkOffscreenWindow *offscreen;
394   gint dx, dy, dw, dh;
395   cairo_surface_t *old_surface;
396
397   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
398
399   if (width < 1)
400     width = 1;
401   if (height < 1)
402     height = 1;
403
404   if (private->destroyed)
405     return;
406
407   dx = x - private->x;
408   dy = y - private->y;
409   dw = width - private->width;
410   dh = height - private->height;
411
412   private->x = x;
413   private->y = y;
414
415   if (private->width != width ||
416       private->height != height)
417     {
418       cairo_t *cr;
419
420       private->width = width;
421       private->height = height;
422
423       old_surface = offscreen->surface;
424       offscreen->surface = cairo_surface_create_similar (old_surface,
425                                                          cairo_surface_get_content (old_surface),
426                                                          width,
427                                                          height);
428
429       cr = cairo_create (offscreen->surface);
430       cairo_set_source_surface (cr, old_surface, 0, 0);
431       cairo_paint (cr);
432       cairo_destroy (cr);
433
434       cairo_surface_destroy (old_surface);
435     }
436
437   if (GDK_WINDOW_IS_MAPPED (private))
438     {
439       // TODO: Only invalidate new area, i.e. for larger windows
440       gdk_window_invalidate_rect (window, NULL, TRUE);
441       _gdk_synthesize_crossing_events_for_geometry_change (window);
442     }
443 }
444
445 static void
446 gdk_offscreen_window_move_resize (GdkWindow *window,
447                                   gboolean   with_move,
448                                   gint       x,
449                                   gint       y,
450                                   gint       width,
451                                   gint       height)
452 {
453   GdkWindowObject *private = (GdkWindowObject *)window;
454   GdkOffscreenWindow *offscreen;
455
456   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
457
458   if (!with_move)
459     {
460       x = private->x;
461       y = private->y;
462     }
463
464   if (width < 0)
465     width = private->width;
466
467   if (height < 0)
468     height = private->height;
469
470   gdk_offscreen_window_move_resize_internal (window, x, y,
471                                              width, height,
472                                              TRUE);
473 }
474
475 static void
476 gdk_offscreen_window_show (GdkWindow *window,
477                            gboolean already_mapped)
478 {
479   GdkWindowObject *private = (GdkWindowObject *)window;
480   GdkRectangle area = { 0, 0, private->width, private->height };
481
482   gdk_window_clear_area (window, 0, 0,
483                          private->width, private->height);
484   gdk_window_invalidate_rect (window, &area, FALSE);
485 }
486
487
488 static void
489 gdk_offscreen_window_hide (GdkWindow *window)
490 {
491   GdkWindowObject *private;
492   GdkOffscreenWindow *offscreen;
493   GdkDisplay *display;
494
495   g_return_if_fail (window != NULL);
496
497   private = (GdkWindowObject*) window;
498   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
499
500   /* May need to break grabs on children */
501   display = gdk_window_get_display (window);
502
503   /* TODO: This needs updating to the new grab world */
504 #if 0
505   if (display->pointer_grab.window != NULL)
506     {
507       if (is_parent_of (window, display->pointer_grab.window))
508         {
509           /* Call this ourselves, even though gdk_display_pointer_ungrab
510              does so too, since we want to pass implicit == TRUE so the
511              broken grab event is generated */
512           _gdk_display_unset_has_pointer_grab (display,
513                                                TRUE,
514                                                FALSE,
515                                                GDK_CURRENT_TIME);
516           gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
517         }
518     }
519 #endif
520 }
521
522 static void
523 gdk_offscreen_window_withdraw (GdkWindow *window)
524 {
525 }
526
527 static GdkEventMask
528 gdk_offscreen_window_get_events (GdkWindow *window)
529 {
530   return 0;
531 }
532
533 static void
534 gdk_offscreen_window_set_events (GdkWindow       *window,
535                                  GdkEventMask     event_mask)
536 {
537 }
538
539 static void
540 gdk_offscreen_window_set_background (GdkWindow      *window,
541                                      cairo_pattern_t *pattern)
542 {
543 }
544
545 static void
546 gdk_offscreen_window_shape_combine_region (GdkWindow       *window,
547                                            const cairo_region_t *shape_region,
548                                            gint             offset_x,
549                                            gint             offset_y)
550 {
551 }
552
553 static void
554 gdk_offscreen_window_input_shape_combine_region (GdkWindow       *window,
555                                                  const cairo_region_t *shape_region,
556                                                  gint             offset_x,
557                                                  gint             offset_y)
558 {
559 }
560
561 static gboolean
562 gdk_offscreen_window_set_static_gravities (GdkWindow *window,
563                                            gboolean   use_static)
564 {
565   return TRUE;
566 }
567
568 static void
569 gdk_offscreen_window_get_geometry (GdkWindow *window,
570                                    gint      *x,
571                                    gint      *y,
572                                    gint      *width,
573                                    gint      *height,
574                                    gint      *depth)
575 {
576   GdkWindowObject *private = (GdkWindowObject *)window;
577
578   g_return_if_fail (window == NULL || GDK_IS_WINDOW (window));
579
580   if (!GDK_WINDOW_DESTROYED (window))
581     {
582       if (x)
583         *x = private->x;
584       if (y)
585         *y = private->y;
586       if (width)
587         *width = private->width;
588       if (height)
589         *height = private->height;
590       if (depth)
591         *depth = private->depth;
592     }
593 }
594
595 static gboolean
596 gdk_offscreen_window_queue_antiexpose (GdkWindow *window,
597                                        cairo_region_t *area)
598 {
599   return FALSE;
600 }
601
602 static void
603 gdk_offscreen_window_translate (GdkWindow      *window,
604                                 cairo_region_t *area,
605                                 gint            dx,
606                                 gint            dy)
607 {
608   GdkOffscreenWindow *offscreen = GDK_OFFSCREEN_WINDOW (((GdkWindowObject *) window)->impl);
609   cairo_t *cr;
610
611   cr = cairo_create (offscreen->surface);
612
613   area = cairo_region_copy (area);
614
615   gdk_cairo_region (cr, area);
616   cairo_clip (cr);
617   
618   /* NB: This is a self-copy and Cairo doesn't support that yet.
619    * So we do a litle trick.
620    */
621   cairo_push_group (cr);
622
623   cairo_set_source_surface (cr, offscreen->surface, dx, dy);
624   cairo_paint (cr);
625
626   cairo_pop_group_to_source (cr);
627   cairo_paint (cr);
628
629   cairo_destroy (cr);
630
631   _gdk_window_add_damage (window, area);
632 }
633
634 /**
635  * gdk_offscreen_window_set_embedder:
636  * @window: a #GdkWindow
637  * @embedder: the #GdkWindow that @window gets embedded in
638  *
639  * Sets @window to be embedded in @embedder.
640  *
641  * To fully embed an offscreen window, in addition to calling this
642  * function, it is also necessary to handle the #GdkWindow::pick-embedded-child
643  * signal on the @embedder and the #GdkWindow::to-embedder and
644  * #GdkWindow::from-embedder signals on @window.
645  *
646  * Since: 2.18
647  */
648 void
649 gdk_offscreen_window_set_embedder (GdkWindow     *window,
650                                    GdkWindow     *embedder)
651 {
652   GdkWindowObject *private = (GdkWindowObject *)window;
653   GdkOffscreenWindow *offscreen;
654
655   g_return_if_fail (GDK_IS_WINDOW (window));
656
657   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
658     return;
659
660   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
661
662   if (embedder)
663     {
664       g_object_ref (embedder);
665       GDK_WINDOW_OBJECT (embedder)->num_offscreen_children++;
666     }
667
668   if (offscreen->embedder)
669     {
670       g_object_unref (offscreen->embedder);
671       GDK_WINDOW_OBJECT (offscreen->embedder)->num_offscreen_children--;
672     }
673
674   offscreen->embedder = embedder;
675 }
676
677 /**
678  * gdk_offscreen_window_get_embedder:
679  * @window: a #GdkWindow
680  *
681  * Gets the window that @window is embedded in.
682  *
683  * Returns: the embedding #GdkWindow, or %NULL if @window is not an
684  *     embedded offscreen window
685  *
686  * Since: 2.18
687  */
688 GdkWindow *
689 gdk_offscreen_window_get_embedder (GdkWindow *window)
690 {
691   GdkWindowObject *private = (GdkWindowObject *)window;
692   GdkOffscreenWindow *offscreen;
693
694   g_return_val_if_fail (GDK_IS_WINDOW (window), NULL);
695
696   if (!GDK_IS_OFFSCREEN_WINDOW (private->impl))
697     return NULL;
698
699   offscreen = GDK_OFFSCREEN_WINDOW (private->impl);
700
701   return offscreen->embedder;
702 }
703
704 static void
705 gdk_offscreen_window_class_init (GdkOffscreenWindowClass *klass)
706 {
707   GdkDrawableClass *drawable_class = GDK_DRAWABLE_CLASS (klass);
708   GObjectClass *object_class = G_OBJECT_CLASS (klass);
709
710   object_class->finalize = gdk_offscreen_window_finalize;
711
712   drawable_class->ref_cairo_surface = gdk_offscreen_window_ref_cairo_surface;
713   drawable_class->get_colormap = gdk_offscreen_window_get_colormap;
714 }
715
716 static void
717 gdk_offscreen_window_impl_iface_init (GdkWindowImplIface *iface)
718 {
719   iface->show = gdk_offscreen_window_show;
720   iface->hide = gdk_offscreen_window_hide;
721   iface->withdraw = gdk_offscreen_window_withdraw;
722   iface->raise = gdk_offscreen_window_raise;
723   iface->lower = gdk_offscreen_window_lower;
724   iface->move_resize = gdk_offscreen_window_move_resize;
725   iface->set_background = gdk_offscreen_window_set_background;
726   iface->get_events = gdk_offscreen_window_get_events;
727   iface->set_events = gdk_offscreen_window_set_events;
728   iface->reparent = gdk_offscreen_window_reparent;
729   iface->get_geometry = gdk_offscreen_window_get_geometry;
730   iface->shape_combine_region = gdk_offscreen_window_shape_combine_region;
731   iface->input_shape_combine_region = gdk_offscreen_window_input_shape_combine_region;
732   iface->set_static_gravities = gdk_offscreen_window_set_static_gravities;
733   iface->queue_antiexpose = gdk_offscreen_window_queue_antiexpose;
734   iface->translate = gdk_offscreen_window_translate;
735   iface->get_root_coords = gdk_offscreen_window_get_root_coords;
736   iface->get_device_state = gdk_offscreen_window_get_device_state;
737   iface->destroy = gdk_offscreen_window_destroy;
738 }