1 /*******************************************************************************
2  * Copyright (c) 2000, 2008 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  * Port to the D programming language:
11  *     Frank Benoit <benoit@tionex.de>
12  *******************************************************************************/
13 module org.eclipse.swt.widgets.Composite;
14 
15 import org.eclipse.swt.widgets.Control;
16 import org.eclipse.swt.widgets.Scrollable;
17 import org.eclipse.swt.widgets.Layout;
18 import org.eclipse.swt.widgets.Decorations;
19 import org.eclipse.swt.widgets.ScrollBar;
20 import org.eclipse.swt.widgets.Shell;
21 import org.eclipse.swt.widgets.Menu;
22 import org.eclipse.swt.widgets.Event;
23 import org.eclipse.swt.widgets.Widget;
24 import org.eclipse.swt.widgets.Display;
25 import org.eclipse.swt.graphics.GCData;
26 
27 import org.eclipse.swt.internal.gtk.OS;
28 import org.eclipse.swt.graphics.GC;
29 import org.eclipse.swt.SWT;
30 import org.eclipse.swt.graphics.Region;
31 import org.eclipse.swt.internal.cairo.Cairo : Cairo;
32 import org.eclipse.swt.internal.gtk.OS;
33 import org.eclipse.swt.graphics.Rectangle;
34 import java.lang.all;
35 
36 /**
37  * Instances of this class are controls which are capable
38  * of containing other controls.
39  * <dl>
40  * <dt><b>Styles:</b></dt>
41  * <dd>NO_BACKGROUND, NO_FOCUS, NO_MERGE_PAINTS, NO_REDRAW_RESIZE, NO_RADIO_GROUP, EMBEDDED, DOUBLE_BUFFERED</dd>
42  * <dt><b>Events:</b></dt>
43  * <dd>(none)</dd>
44  * </dl>
45  * <p>
46  * Note: The <code>NO_BACKGROUND</code>, <code>NO_FOCUS</code>, <code>NO_MERGE_PAINTS</code>,
47  * and <code>NO_REDRAW_RESIZE</code> styles are intended for use with <code>Canvas</code>.
48  * They can be used with <code>Composite</code> if you are drawing your own, but their
49  * behavior is undefined if they are used with subclasses of <code>Composite</code> other
50  * than <code>Canvas</code>.
51  * </p><p>
52  * Note: The <code>CENTER</code> style, although undefined for composites, has the
53  * same value as <code>EMBEDDED</code> (which is used to embed widgets from other
54  * widget toolkits into SWT).  On some operating systems (GTK, Motif), this may cause
55  * the children of this composite to be obscured.  The <code>EMBEDDED</code> style
56  * is for use by other widget toolkits and should normally never be used.
57  * </p><p>
58  * This class may be subclassed by custom control implementors
59  * who are building controls that are constructed from aggregates
60  * of other controls.
61  * </p>
62  *
63  * @see Canvas
64  * @see <a href="http://www.eclipse.org/swt/snippets/#composite">Composite snippets</a>
65  * @see <a href="http://www.eclipse.org/swt/">Sample code and further information</a>
66  */
67 public class Composite : Scrollable {
68 
69     alias Scrollable.computeSize computeSize;
70     alias Scrollable.fixStyle fixStyle;
71     alias Scrollable.forceFocus forceFocus;
72     alias Scrollable.gtk_button_press_event gtk_button_press_event;
73     alias Scrollable.moveAbove moveAbove;
74     alias Scrollable.moveBelow moveBelow;
75     alias Scrollable.setBounds setBounds;
76     alias Scrollable.translateMnemonic translateMnemonic;
77     alias Scrollable.translateTraversal translateTraversal;
78 
79     public size_t  embeddedHandle;
80     GtkIMContext* imHandle_;
81     GtkWidget* socketHandle;
82     Layout layout_;
83     Control[] tabList;
84     int layoutCount, backgroundMode;
85 
86     static const String NO_INPUT_METHOD = "org.eclipse.swt.internal.gtk.noInputMethod"; //$NON-NLS-1$
87 
88 this () {
89     /* Do nothing */
90 }
91 
92 /**
93  * Constructs a new instance of this class given its parent
94  * and a style value describing its behavior and appearance.
95  * <p>
96  * The style value is either one of the style constants defined in
97  * class <code>SWT</code> which is applicable to instances of this
98  * class, or must be built by <em>bitwise OR</em>'ing together
99  * (that is, using the <code>int</code> "|" operator) two or more
100  * of those <code>SWT</code> style constants. The class description
101  * lists the style constants that are applicable to the class.
102  * Style bits are also inherited from superclasses.
103  * </p>
104  *
105  * @param parent a widget which will be the parent of the new instance (cannot be null)
106  * @param style the style of widget to construct
107  *
108  * @exception IllegalArgumentException <ul>
109  *    <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
110  * </ul>
111  * @exception SWTException <ul>
112  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the parent</li>
113  * </ul>
114  *
115  * @see SWT#NO_BACKGROUND
116  * @see SWT#NO_FOCUS
117  * @see SWT#NO_MERGE_PAINTS
118  * @see SWT#NO_REDRAW_RESIZE
119  * @see SWT#NO_RADIO_GROUP
120  * @see Widget#getStyle
121  */
122 public this (Composite parent, int style) {
123     super (parent, checkStyle (style));
124 }
125 
126 static int checkStyle (int style) {
127     style &= ~SWT.TRANSPARENT;
128     return style;
129 }
130 
131 Control [] _getChildren () {
132     auto parentHandle = parentingHandle ();
133     auto list = OS.gtk_container_get_children (cast(GtkContainer*)parentHandle);
134     if (list is null) return new Control [0];
135     int count = OS.g_list_length (list);
136     Control [] children = new Control [count];
137     int i = 0;
138     auto temp = list;
139     while (temp !is null) {
140         auto handle = cast(GtkWidget*)OS.g_list_data (temp);
141         if (handle !is null) {
142             Widget widget = display.getWidget (handle);
143             if (widget !is null && widget !is this) {
144                 if (auto c = cast(Control)widget) {
145                     children [i++] = c;
146                 }
147             }
148         }
149         temp = cast(GList*)OS.g_list_next (temp);
150     }
151     OS.g_list_free (list);
152     if (i is count) return children;
153     Control [] newChildren = new Control [i];
154     System.arraycopy (children, 0, newChildren, 0, i);
155     return newChildren;
156 }
157 
158 Control [] _getTabList () {
159     if (tabList is null) return tabList;
160     int count = 0;
161     for (int i=0; i<tabList.length; i++) {
162         if (!tabList [i].isDisposed ()) count++;
163     }
164     if (count is tabList.length) return tabList;
165     Control [] newList = new Control [count];
166     int index = 0;
167     for (int i=0; i<tabList.length; i++) {
168         if (!tabList [i].isDisposed ()) {
169             newList [index++] = tabList [i];
170         }
171     }
172     tabList = newList;
173     return tabList;
174 }
175 
176 /**
177  * Clears any data that has been cached by a Layout for all widgets that
178  * are in the parent hierarchy of the changed control up to and including the
179  * receiver.  If an ancestor does not have a layout, it is skipped.
180  *
181  * @param changed an array of controls that changed state and require a recalculation of size
182  *
183  * @exception IllegalArgumentException <ul>
184  *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
185  *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
186  * </ul>
187  * @exception SWTException <ul>
188  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
189  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
190  * </ul>
191  *
192  * @since 3.1
193  */
194 public void changed (Control[] changed) {
195     checkWidget ();
196     if (changed is null) error (SWT.ERROR_INVALID_ARGUMENT);
197     for (int i=0; i<changed.length; i++) {
198         Control control = changed [i];
199         if (control is null) error (SWT.ERROR_INVALID_ARGUMENT);
200         if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
201         bool ancestor = false;
202         Composite composite = control.parent;
203         while (composite !is null) {
204             ancestor = composite is this;
205             if (ancestor) break;
206             composite = composite.parent;
207         }
208         if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
209     }
210     for (int i=0; i<changed.length; i++) {
211         Control child = changed [i];
212         Composite composite = child.parent;
213         while (child !is this) {
214             if (composite.layout_ is null || !composite.layout_.flushCache (child)) {
215                 composite.state |= LAYOUT_CHANGED;
216             }
217             child = composite;
218             composite = child.parent;
219         }
220     }
221 }
222 
223 override void checkBuffered () {
224     if ((style & SWT.DOUBLE_BUFFERED) is 0 && (style & SWT.NO_BACKGROUND) !is 0) {
225         return;
226     }
227     super.checkBuffered();
228 }
229 
230 override protected void checkSubclass () {
231     /* Do nothing - Subclassing is allowed */
232 }
233 
234 override GtkStyle* childStyle () {
235     if (scrolledHandle !is null) return null;
236     return super.childStyle ();
237 }
238 
239 override public Point computeSize (int wHint, int hHint, bool changed) {
240     checkWidget ();
241     if (wHint !is SWT.DEFAULT && wHint < 0) wHint = 0;
242     if (hHint !is SWT.DEFAULT && hHint < 0) hHint = 0;
243     Point size;
244     if (layout_ !is null) {
245         if (wHint is SWT.DEFAULT || hHint is SWT.DEFAULT) {
246             changed |= (state & LAYOUT_CHANGED) !is 0;
247             size = layout_.computeSize (this, wHint, hHint, changed);
248             state &= ~LAYOUT_CHANGED;
249         } else {
250             size = new Point (wHint, hHint);
251         }
252     } else {
253         size = minimumSize (wHint, hHint, changed);
254     }
255     if (size.x is 0) size.x = DEFAULT_WIDTH;
256     if (size.y is 0) size.y = DEFAULT_HEIGHT;
257     if (wHint !is SWT.DEFAULT) size.x = wHint;
258     if (hHint !is SWT.DEFAULT) size.y = hHint;
259     Rectangle trim = computeTrim (0, 0, size.x, size.y);
260     return new Point (trim.width, trim.height);
261 }
262 
263 override Control [] computeTabList () {
264     Control[] result = super.computeTabList ();
265     if (result.length is 0) return result;
266     Control [] list = tabList !is null ? _getTabList () : _getChildren ();
267     for (int i=0; i<list.length; i++) {
268         Control child = list [i];
269         Control [] childList = child.computeTabList ();
270         if (childList.length !is 0) {
271             Control [] newResult = new Control [result.length + childList.length];
272             System.arraycopy (result, 0, newResult, 0, result.length);
273             System.arraycopy (childList, 0, newResult, result.length, childList.length);
274             result = newResult;
275         }
276     }
277     return result;
278 }
279 
280 override void createHandle (int index) {
281     state |= HANDLE | CANVAS;
282     bool scrolled = (style & (SWT.H_SCROLL | SWT.V_SCROLL)) !is 0;
283     if (!scrolled) state |= THEME_BACKGROUND;
284     createHandle (index, true, scrolled || (style & SWT.BORDER) !is 0);
285 }
286 
287 void createHandle (int index, bool fixed, bool scrolled) {
288     if (scrolled) {
289         if (fixed) {
290             fixedHandle = cast(GtkWidget*) OS.g_object_new (display.gtk_fixed_get_type (), null);
291             if (fixedHandle is null) error (SWT.ERROR_NO_HANDLES);
292             OS.gtk_fixed_set_has_window (cast(GtkFixed*)fixedHandle, true);
293         }
294         auto vadj = cast(GtkAdjustment*)OS.gtk_adjustment_new (0, 0, 100, 1, 10, 10);
295         if (vadj is null) error (SWT.ERROR_NO_HANDLES);
296         auto hadj = cast(GtkAdjustment*)OS.gtk_adjustment_new (0, 0, 100, 1, 10, 10);
297         if (hadj is null) error (SWT.ERROR_NO_HANDLES);
298         scrolledHandle = cast(GtkWidget*) OS.gtk_scrolled_window_new (hadj, vadj);
299         if (scrolledHandle is null) SWT.error (SWT.ERROR_NO_HANDLES);
300     }
301     handle = cast(GtkWidget*)OS.g_object_new (display.gtk_fixed_get_type (), null);
302     if (handle is null) SWT.error (SWT.ERROR_NO_HANDLES);
303     OS.gtk_fixed_set_has_window (cast(GtkFixed*)handle, true);
304     OS.GTK_WIDGET_SET_FLAGS(handle, OS.GTK_CAN_FOCUS);
305     if ((style & SWT.EMBEDDED) is 0) {
306         if ((state & CANVAS) !is 0) {
307             /* Prevent an input method context from being created for the Browser widget */
308             if (display.getData (NO_INPUT_METHOD) is null) {
309                 imHandle_ = OS.gtk_im_multicontext_new ();
310                 if (imHandle_ is null) error (SWT.ERROR_NO_HANDLES);
311             }
312         }
313     }
314     if (scrolled) {
315         if (fixed) OS.gtk_container_add (cast(GtkContainer*)fixedHandle, scrolledHandle);
316         /*
317         * Force the scrolledWindow to have a single child that is
318         * not scrolled automatically.  Calling gtk_container_add()
319         * seems to add the child correctly but cause a warning.
320         */
321         bool warnings = display.getWarnings ();
322         display.setWarnings (false);
323         OS.gtk_container_add (cast(GtkContainer*)scrolledHandle, handle);
324         display.setWarnings (warnings);
325 
326         int hsp = (style & SWT.H_SCROLL) !is 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER;
327         int vsp = (style & SWT.V_SCROLL) !is 0 ? OS.GTK_POLICY_ALWAYS : OS.GTK_POLICY_NEVER;
328         OS.gtk_scrolled_window_set_policy (cast(GtkScrolledWindow*)scrolledHandle, hsp, vsp);
329         if (hasBorder ()) {
330             OS.gtk_scrolled_window_set_shadow_type (cast(GtkScrolledWindow*)scrolledHandle, OS.GTK_SHADOW_ETCHED_IN);
331         }
332     }
333     if ((style & SWT.EMBEDDED) !is 0) {
334         socketHandle = OS.gtk_socket_new ();
335         if (socketHandle is null) SWT.error (SWT.ERROR_NO_HANDLES);
336         OS.gtk_container_add (cast(GtkContainer*)handle, cast(GtkWidget*)socketHandle);
337     }
338     if ((style & SWT.NO_REDRAW_RESIZE) !is 0 && (style & SWT.RIGHT_TO_LEFT) is 0) {
339         OS.gtk_widget_set_redraw_on_allocate (handle, false);
340     }
341     /*
342     * Bug in GTK.  When a widget is double buffered and the back
343     * pixmap is null, the double buffer pixmap is filled with the
344     * background of the widget rather than the current contents of
345     * the screen.  If nothing is drawn during an expose event,
346     * the pixels are altered.  The fix is to clear double buffering
347     * when NO_BACKGROUND is set and DOUBLE_BUFFERED
348     * is not explicitly set.
349     */
350     if ((style & SWT.DOUBLE_BUFFERED) is 0 && (style & SWT.NO_BACKGROUND) !is 0) {
351         OS.gtk_widget_set_double_buffered (handle, false);
352     }
353 }
354 
355 override void deregister () {
356     super.deregister ();
357     if (socketHandle !is null) display.removeWidget (cast(GtkWidget*)socketHandle);
358 }
359 
360 void drawBackground (GC gc, int x, int y, int width, int height) {
361     Control control = findBackgroundControl ();
362     if (control !is null) {
363         GCData data = gc.getGCData ();
364         auto cairo = data.cairo;
365         if (cairo !is null) {
366             Cairo.cairo_save (cairo);
367             if (control.backgroundImage !is null) {
368                 Point pt = display.map (this, control, 0, 0);
369                 Cairo.cairo_translate (cairo, -pt.x, -pt.y);
370                 x += pt.x;
371                 y += pt.y;
372                 auto xDisplay = OS.GDK_DISPLAY ();
373                 auto xVisual = OS.gdk_x11_visual_get_xvisual (OS.gdk_visual_get_system());
374                 auto drawable = control.backgroundImage.pixmap;
375                 auto xDrawable = OS.GDK_PIXMAP_XID (drawable);
376                 int w, h;
377                 OS.gdk_drawable_get_size (cast(GdkDrawable*)drawable, &w, &h);
378                 auto surface = Cairo.cairo_xlib_surface_create (xDisplay, xDrawable, xVisual, w, h);
379                 if (surface is null) error (SWT.ERROR_NO_HANDLES);
380                 auto pattern = Cairo.cairo_pattern_create_for_surface (surface);
381                 if (pattern is null) error (SWT.ERROR_NO_HANDLES);
382                 Cairo.cairo_pattern_set_extend (pattern, Cairo.CAIRO_EXTEND_REPEAT);
383                 if ((data.style & SWT.MIRRORED) !is 0) {
384                     double[] matrix = [-1.0, 0, 0, 1, 0, 0 ];
385                     Cairo.cairo_pattern_set_matrix(pattern, cast(cairo_matrix_t*)matrix.ptr);
386                 }
387                 Cairo.cairo_set_source (cairo, pattern);
388                 Cairo.cairo_surface_destroy (surface);
389                 Cairo.cairo_pattern_destroy (pattern);
390             } else {
391                 GdkColor* color = control.getBackgroundColor ();
392                 Cairo.cairo_set_source_rgba (cairo, (color.red & 0xFFFF) / cast(float)0xFFFF, (color.green & 0xFFFF) / cast(float)0xFFFF, (color.blue & 0xFFFF) / cast(float)0xFFFF, data.alpha / cast(float)0xFF);
393             }
394             Cairo.cairo_rectangle (cairo, x, y, width, height);
395             Cairo.cairo_fill (cairo);
396             Cairo.cairo_restore (cairo);
397         } else {
398             auto gdkGC = gc.handle;
399             GdkGCValues* values = new GdkGCValues ();
400             OS.gdk_gc_get_values (gdkGC, values);
401             if (control.backgroundImage !is null) {
402                 Point pt = display.map (this, control, 0, 0);
403                 OS.gdk_gc_set_fill (gdkGC, OS.GDK_TILED);
404                 OS.gdk_gc_set_ts_origin (gdkGC, -pt.x, -pt.y);
405                 OS.gdk_gc_set_tile (gdkGC, control.backgroundImage.pixmap);
406                 OS.gdk_draw_rectangle (data.drawable, gdkGC, 1, x, y, width, height);
407                 OS.gdk_gc_set_fill (gdkGC, values.fill);
408                 OS.gdk_gc_set_ts_origin (gdkGC, values.ts_x_origin, values.ts_y_origin);
409             } else {
410                 GdkColor* color = control.getBackgroundColor ();
411                 OS.gdk_gc_set_foreground (gdkGC, color);
412                 OS.gdk_draw_rectangle (data.drawable, gdkGC, 1, x, y, width, height);
413                 color.pixel = values.foreground.pixel;
414                 OS.gdk_gc_set_foreground (gdkGC, color);
415             }
416         }
417     } else {
418         gc.fillRectangle (x, y, width, height);
419     }
420 }
421 
422 override void enableWidget (bool enabled) {
423     if ((state & CANVAS) !is 0) return;
424     super.enableWidget (enabled);
425 }
426 
427 Composite findDeferredControl () {
428     return layoutCount > 0 ? this : parent.findDeferredControl ();
429 }
430 
431 override Menu [] findMenus (Control control) {
432     if (control is this) return new Menu [0];
433     Menu[] result = super.findMenus (control);
434     Control [] children = _getChildren ();
435     for (int i=0; i<children.length; i++) {
436         Control child = children [i];
437         Menu [] menuList = child.findMenus (control);
438         if (menuList.length !is 0) {
439             Menu [] newResult = new Menu [result.length + menuList.length];
440             System.arraycopy (result, 0, newResult, 0, result.length);
441             System.arraycopy (menuList, 0, newResult, result.length, menuList.length);
442             result = newResult;
443         }
444     }
445     return result;
446 }
447 
448 override void fixChildren (Shell newShell, Shell oldShell, Decorations newDecorations, Decorations oldDecorations, Menu [] menus) {
449     super.fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
450     Control [] children = _getChildren ();
451     for (int i=0; i<children.length; i++) {
452         children [i].fixChildren (newShell, oldShell, newDecorations, oldDecorations, menus);
453     }
454 }
455 
456 override
457 void fixModal(GtkWidget* group, GtkWidget* modalGroup)  {
458     Control[] controls = _getChildren ();
459     for (int i = 0; i < controls.length; i++) {
460         controls[i].fixModal (group, modalGroup);
461     }
462 }
463 
464 override void fixStyle () {
465     super.fixStyle ();
466     if (scrolledHandle is null) fixStyle (handle);
467     Control[] children = _getChildren ();
468     for (int i = 0; i < children.length; i++) {
469         children [i].fixStyle ();
470     }
471 }
472 
473 void fixTabList (Control control) {
474     if (tabList is null) return;
475     int count = 0;
476     for (int i=0; i<tabList.length; i++) {
477         if (tabList [i] is control) count++;
478     }
479     if (count is 0) return;
480     Control [] newList = null;
481     ptrdiff_t length = tabList.length - count;
482     if (length !is 0) {
483         newList = new Control [length];
484         int index = 0;
485         for (int i=0; i<tabList.length; i++) {
486             if (tabList [i] !is control) {
487                 newList [index++] = tabList [i];
488             }
489         }
490     }
491     tabList = newList;
492 }
493 
494 void fixZOrder () {
495     if ((state & CANVAS) !is 0) return;
496     auto parentHandle = parentingHandle ();
497     auto parentWindow = OS.GTK_WIDGET_WINDOW (cast(GtkWidget*)parentHandle);
498     if (parentWindow is null) return;
499     GObject* userData;
500     auto windowList = OS.gdk_window_get_children (parentWindow);
501     if (windowList !is null) {
502         auto windows = windowList;
503         while (windows !is null) {
504             auto window = cast(GdkDrawable*)OS.g_list_data (windows);
505             if (window !is redrawWindow) {
506                 OS.gdk_window_get_user_data (window, cast(void**)&userData);
507                 if (userData is null || OS.G_OBJECT_TYPE (cast(GTypeInstance*)userData) !is display.gtk_fixed_get_type ()) {
508                     OS.gdk_window_lower (window);
509                 }
510             }
511             windows = cast(GList*)OS.g_list_next (windows);
512         }
513         OS.g_list_free (windowList);
514     }
515 }
516 
517 override GtkWidget* focusHandle () {
518     if (socketHandle !is null) return socketHandle;
519     return super.focusHandle ();
520 }
521 
522 override bool forceFocus (GtkWidget* focusHandle) {
523     if (socketHandle !is null) OS.GTK_WIDGET_SET_FLAGS (focusHandle, OS.GTK_CAN_FOCUS);
524     bool result = super.forceFocus (focusHandle);
525     if (socketHandle !is null) OS.GTK_WIDGET_UNSET_FLAGS (focusHandle, OS.GTK_CAN_FOCUS);
526     return result;
527 }
528 
529 /**
530  * Returns the receiver's background drawing mode. This
531  * will be one of the following constants defined in class
532  * <code>SWT</code>:
533  * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
534  * <code>INHERTIT_FORCE</code>.
535  *
536  * @return the background mode
537  *
538  * @exception SWTException <ul>
539  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
540  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
541  * </ul>
542  *
543  * @see SWT
544  *
545  * @since 3.2
546  */
547 public int getBackgroundMode () {
548     checkWidget ();
549     return backgroundMode;
550 }
551 
552 /**
553  * Returns a (possibly empty) array containing the receiver's children.
554  * Children are returned in the order that they are drawn.  The topmost
555  * control appears at the beginning of the array.  Subsequent controls
556  * draw beneath this control and appear later in the array.
557  * <p>
558  * Note: This is not the actual structure used by the receiver
559  * to maintain its list of children, so modifying the array will
560  * not affect the receiver.
561  * </p>
562  *
563  * @return an array of children
564  *
565  * @see Control#moveAbove
566  * @see Control#moveBelow
567  *
568  * @exception SWTException <ul>
569  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
570  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
571  * </ul>
572  */
573 public Control [] getChildren () {
574     checkWidget();
575     return _getChildren ();
576 }
577 
578 int getChildrenCount () {
579     /*
580     * NOTE: The current implementation will count
581     * non-registered children.
582     */
583     auto list = OS.gtk_container_get_children (cast(GtkContainer*)handle);
584     if (list is null) return 0;
585     int count = OS.g_list_length (list);
586     OS.g_list_free (list);
587     return count;
588 }
589 
590 override public Rectangle getClientArea () {
591     checkWidget();
592     if ((state & CANVAS) !is 0) {
593         if ((state & ZERO_WIDTH) !is 0 && (state & ZERO_HEIGHT) !is 0) {
594             return new Rectangle (0, 0, 0, 0);
595         }
596         forceResize ();
597         auto clientHandle = clientHandle ();
598         int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (clientHandle);
599         int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (clientHandle);
600         return new Rectangle (0, 0, width, height);
601     }
602     return super.getClientArea();
603 }
604 
605 override
606 int getClientWidth() {
607     return (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (clientHandle ());
608 }
609 
610 /**
611  * Returns layout which is associated with the receiver, or
612  * null if one has not been set.
613  *
614  * @return the receiver's layout or null
615  *
616  * @exception SWTException <ul>
617  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
618  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
619  * </ul>
620  */
621 public Layout getLayout () {
622     checkWidget();
623     return layout_;
624 }
625 
626 /**
627  * Returns <code>true</code> if the receiver has deferred
628  * the performing of layout, and <code>false</code> otherwise.
629  *
630  * @return the receiver's deferred layout state
631  *
632  * @exception SWTException <ul>
633  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
634  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
635  * </ul>
636  *
637  * @see #setLayoutDeferred(bool)
638  * @see #isLayoutDeferred()
639  *
640  * @since 3.1
641  */
642 public bool getLayoutDeferred () {
643     checkWidget ();
644     return layoutCount > 0 ;
645 }
646 
647 /**
648  * Gets the (possibly empty) tabbing order for the control.
649  *
650  * @return tabList the ordered list of controls representing the tab order
651  *
652  * @exception SWTException <ul>
653  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
654  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
655  * </ul>
656  *
657  * @see #setTabList
658  */
659 public Control [] getTabList () {
660     checkWidget ();
661     Control [] tabList = _getTabList ();
662     if (tabList is null) {
663         int count = 0;
664         Control [] list =_getChildren ();
665         for (int i=0; i<list.length; i++) {
666             if (list [i].isTabGroup ()) count++;
667         }
668         tabList = new Control [count];
669         int index = 0;
670         for (int i=0; i<list.length; i++) {
671             if (list [i].isTabGroup ()) {
672                 tabList [index++] = list [i];
673             }
674         }
675     }
676     return tabList;
677 }
678 
679 override int gtk_button_press_event (GtkWidget* widget, GdkEventButton* event) {
680     auto result = super.gtk_button_press_event (widget, event);
681     if (result !is 0) return result;
682     if ((state & CANVAS) !is 0) {
683         if ((style & SWT.NO_FOCUS) is 0 && hooksKeys ()) {
684             if (event.button is 1) {
685                 if (getChildrenCount () is 0) setFocus ();
686             }
687         }
688     }
689     return result;
690 }
691 
692 override int gtk_expose_event (GtkWidget* widget, GdkEventExpose* eventPtr) {
693     if ((state & OBSCURED) !is 0) return 0;
694     if ((state & CANVAS) is 0) {
695         return super.gtk_expose_event (widget, eventPtr);
696     }
697     if ((style & SWT.NO_MERGE_PAINTS) is 0) {
698         return super.gtk_expose_event (widget, eventPtr);
699     }
700     if (!hooks (SWT.Paint) && !filters (SWT.Paint)) return 0;
701     GdkEventExpose* gdkEvent = eventPtr;
702     GdkRectangle* rectangles;
703     int n_rectangles;
704     OS.gdk_region_get_rectangles (gdkEvent.region, &rectangles, &n_rectangles);
705     for (int i=0; i<n_rectangles; i++) {
706         Event event = new Event ();
707         event.x = rectangles[i].x;
708         event.y = rectangles[i].y;
709         event.width = rectangles[i].width;
710         event.height = rectangles[i].height;
711         if ((style & SWT.MIRRORED) !is 0) event.x = getClientWidth () - event.width - event.x;
712         auto damageRgn = OS.gdk_region_new ();
713         OS.gdk_region_union_with_rect (damageRgn, rectangles + i );
714         GCData data = new GCData ();
715         data.damageRgn = damageRgn;
716         GC gc = event.gc = GC.gtk_new (this, data);
717         OS.gdk_gc_set_clip_region (gc.handle, damageRgn);
718         sendEvent (SWT.Paint, event);
719         gc.dispose ();
720         OS.gdk_region_destroy (damageRgn);
721         event.gc = null;
722     }
723     OS.g_free (rectangles);
724     return 0;
725 }
726 
727 override int gtk_key_press_event (GtkWidget* widget, GdkEventKey* event) {
728     auto result = super.gtk_key_press_event (widget, event);
729     if (result !is 0) return result;
730     /*
731     * Feature in GTK.  The default behavior when the return key
732     * is pressed is to select the default button.  This is not the
733     * expected behavior for Composite and its subclasses.  The
734     * fix is to avoid calling the default handler.
735     */
736     if ((state & CANVAS) !is 0 && socketHandle is null) {
737         GdkEventKey* keyEvent = event;
738         int key = keyEvent.keyval;
739         switch (key) {
740             case OS.GDK_Return:
741             case OS.GDK_KP_Enter: return 1;
742             default:
743         }
744     }
745     return result;
746 }
747 
748 override int gtk_focus (GtkWidget* widget, ptrdiff_t directionType) {
749     if (widget is socketHandle) return 0;
750     return super.gtk_focus (widget, directionType);
751 }
752 
753 override int gtk_focus_in_event (GtkWidget* widget, GdkEventFocus* event) {
754     int result = super.gtk_focus_in_event (widget, event);
755     return (state & CANVAS) !is 0 ? 1 : result;
756 }
757 
758 override int gtk_focus_out_event (GtkWidget* widget, GdkEventFocus* event) {
759     auto result = super.gtk_focus_out_event (widget, event);
760     return (state & CANVAS) !is 0 ? 1 : result;
761 }
762 
763 override int gtk_map (GtkWidget* widget) {
764     fixZOrder ();
765     return 0;
766 }
767 
768 override int gtk_realize (GtkWidget* widget) {
769     auto result = super.gtk_realize (widget);
770     if ((style & SWT.NO_BACKGROUND) !is 0) {
771         auto window = OS.GTK_WIDGET_WINDOW (paintHandle ());
772         if (window !is null) OS.gdk_window_set_back_pixmap (window, null, false);
773     }
774     if (socketHandle !is null) {
775         embeddedHandle = OS.gtk_socket_get_id (cast(GtkSocket*)socketHandle);
776     }
777     return result;
778 }
779 
780 override int gtk_scroll_child (GtkWidget* widget, ptrdiff_t scrollType, ptrdiff_t horizontal) {
781     /* Stop GTK scroll child signal for canvas */
782     OS.g_signal_stop_emission_by_name (widget, OS.scroll_child.ptr);
783     return 1;
784 }
785 
786 override int gtk_style_set (GtkWidget* widget, ptrdiff_t previousStyle) {
787     auto result = super.gtk_style_set (widget, previousStyle);
788     if ((style & SWT.NO_BACKGROUND) !is 0) {
789         auto window = OS.GTK_WIDGET_WINDOW (paintHandle ());
790         if (window !is null) OS.gdk_window_set_back_pixmap (window, null, false);
791     }
792     return result;
793 }
794 
795 bool hasBorder () {
796     return (style & SWT.BORDER) !is 0;
797 }
798 
799 override void hookEvents () {
800     super.hookEvents ();
801     if ((state & CANVAS) !is 0) {
802         OS.gtk_widget_add_events (handle, OS.GDK_POINTER_MOTION_HINT_MASK);
803         if (scrolledHandle !is null) {
804             OS.g_signal_connect_closure (scrolledHandle, OS.scroll_child.ptr, display.closures [SCROLL_CHILD], false);
805         }
806     }
807 }
808 
809 bool hooksKeys () {
810     return hooks (SWT.KeyDown) || hooks (SWT.KeyUp);
811 }
812 
813 override GtkIMContext* imHandle () {
814     return imHandle_;
815 }
816 
817 /**
818  * Returns <code>true</code> if the receiver or any ancestor
819  * up to and including the receiver's nearest ancestor shell
820  * has deferred the performing of layouts.  Otherwise, <code>false</code>
821  * is returned.
822  *
823  * @return the receiver's deferred layout state
824  *
825  * @exception SWTException <ul>
826  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
827  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
828  * </ul>
829  *
830  * @see #setLayoutDeferred(bool)
831  * @see #getLayoutDeferred()
832  *
833  * @since 3.1
834  */
835 public bool isLayoutDeferred () {
836     checkWidget ();
837     return findDeferredControl () !is null;
838 }
839 
840 override bool isTabGroup() {
841     if ((state & CANVAS) !is 0) return true;
842     return super.isTabGroup();
843 }
844 
845 /**
846  * If the receiver has a layout, asks the layout to <em>lay out</em>
847  * (that is, set the size and location of) the receiver's children.
848  * If the receiver does not have a layout, do nothing.
849  * <p>
850  * This is equivalent to calling <code>layout(true)</code>.
851  * </p>
852  * <p>
853  * Note: Layout is different from painting. If a child is
854  * moved or resized such that an area in the parent is
855  * exposed, then the parent will paint. If no child is
856  * affected, the parent will not paint.
857  * </p>
858  *
859  * @exception SWTException <ul>
860  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
861  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
862  * </ul>
863  */
864 public void layout () {
865     checkWidget ();
866     layout (true);
867 }
868 
869 /**
870  * If the receiver has a layout, asks the layout to <em>lay out</em>
871  * (that is, set the size and location of) the receiver's children.
872  * If the argument is <code>true</code> the layout must not rely
873  * on any information it has cached about the immediate children. If it
874  * is <code>false</code> the layout may (potentially) optimize the
875  * work it is doing by assuming that none of the receiver's
876  * children has changed state since the last layout.
877  * If the receiver does not have a layout, do nothing.
878  * <p>
879  * If a child is resized as a result of a call to layout, the
880  * resize event will invoke the layout of the child.  The layout
881  * will cascade down through all child widgets in the receiver's widget
882  * tree until a child is encountered that does not resize.  Note that
883  * a layout due to a resize will not flush any cached information
884  * (same as <code>layout(false)</code>).
885  * </p>
886  * <p>
887  * Note: Layout is different from painting. If a child is
888  * moved or resized such that an area in the parent is
889  * exposed, then the parent will paint. If no child is
890  * affected, the parent will not paint.
891  * </p>
892  *
893  * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
894  *
895  * @exception SWTException <ul>
896  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
897  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
898  * </ul>
899  */
900 public void layout (bool changed) {
901     checkWidget ();
902     if (layout_ is null) return;
903     layout (changed, false);
904 }
905 
906 /**
907  * If the receiver has a layout, asks the layout to <em>lay out</em>
908  * (that is, set the size and location of) the receiver's children.
909  * If the changed argument is <code>true</code> the layout must not rely
910  * on any information it has cached about its children. If it
911  * is <code>false</code> the layout may (potentially) optimize the
912  * work it is doing by assuming that none of the receiver's
913  * children has changed state since the last layout.
914  * If the all argument is <code>true</code> the layout will cascade down
915  * through all child widgets in the receiver's widget tree, regardless of
916  * whether the child has changed size.  The changed argument is applied to
917  * all layouts.  If the all argument is <code>false</code>, the layout will
918  * <em>not</em> cascade down through all child widgets in the receiver's widget
919  * tree.  However, if a child is resized as a result of a call to layout, the
920  * resize event will invoke the layout of the child.  Note that
921  * a layout due to a resize will not flush any cached information
922  * (same as <code>layout(false)</code>).
923  * </p>
924  * <p>
925  * Note: Layout is different from painting. If a child is
926  * moved or resized such that an area in the parent is
927  * exposed, then the parent will paint. If no child is
928  * affected, the parent will not paint.
929  * </p>
930  *
931  * @param changed <code>true</code> if the layout must flush its caches, and <code>false</code> otherwise
932  * @param all <code>true</code> if all children in the receiver's widget tree should be laid out, and <code>false</code> otherwise
933  *
934  * @exception SWTException <ul>
935  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
936  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
937  * </ul>
938  *
939  * @since 3.1
940  */
941 public void layout (bool changed, bool all) {
942     checkWidget ();
943     if (layout_ is null && !all) return;
944     markLayout (changed, all);
945     updateLayout (all);
946 }
947 
948 /**
949  * Forces a lay out (that is, sets the size and location) of all widgets that
950  * are in the parent hierarchy of the changed control up to and including the
951  * receiver.  The layouts in the hierarchy must not rely on any information
952  * cached about the changed control or any of its ancestors.  The layout may
953  * (potentially) optimize the work it is doing by assuming that none of the
954  * peers of the changed control have changed state since the last layout.
955  * If an ancestor does not have a layout, skip it.
956  * <p>
957  * Note: Layout is different from painting. If a child is
958  * moved or resized such that an area in the parent is
959  * exposed, then the parent will paint. If no child is
960  * affected, the parent will not paint.
961  * </p>
962  *
963  * @param changed a control that has had a state change which requires a recalculation of its size
964  *
965  * @exception IllegalArgumentException <ul>
966  *    <li>ERROR_INVALID_ARGUMENT - if the changed array is null any of its controls are null or have been disposed</li>
967  *    <li>ERROR_INVALID_PARENT - if any control in changed is not in the widget tree of the receiver</li>
968  * </ul>
969  * @exception SWTException <ul>
970  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
971  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
972  * </ul>
973  *
974  * @since 3.1
975  */
976 public void layout (Control [] changed) {
977     checkWidget ();
978     if (changed is null) error (SWT.ERROR_INVALID_ARGUMENT);
979     for (int i=0; i<changed.length; i++) {
980         Control control = changed [i];
981         if (control is null) error (SWT.ERROR_INVALID_ARGUMENT);
982         if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
983         bool ancestor = false;
984         Composite composite = control.parent;
985         while (composite !is null) {
986             ancestor = composite is this;
987             if (ancestor) break;
988             composite = composite.parent;
989         }
990         if (!ancestor) error (SWT.ERROR_INVALID_PARENT);
991     }
992     int updateCount = 0;
993     Composite [] update = new Composite [16];
994     for (int i=0; i<changed.length; i++) {
995         Control child = changed [i];
996         Composite composite = child.parent;
997         while (child !is this) {
998             if (composite.layout_ !is null) {
999                 composite.state |= LAYOUT_NEEDED;
1000                 if (!composite.layout_.flushCache (child)) {
1001                     composite.state |= LAYOUT_CHANGED;
1002                 }
1003             }
1004             if (updateCount is update.length) {
1005                 Composite [] newUpdate = new Composite [update.length + 16];
1006                 System.arraycopy (update, 0, newUpdate, 0, update.length);
1007                 update = newUpdate;
1008             }
1009             child = update [updateCount++] = composite;
1010             composite = child.parent;
1011         }
1012     }
1013     for (int i=updateCount-1; i>=0; i--) {
1014         update [i].updateLayout (false);
1015     }
1016 }
1017 
1018 override void markLayout (bool changed, bool all) {
1019     if (layout_ !is null) {
1020         state |= LAYOUT_NEEDED;
1021         if (changed) state |= LAYOUT_CHANGED;
1022     }
1023     if (all) {
1024         Control [] children = _getChildren ();
1025         for (int i=0; i<children.length; i++) {
1026             children [i].markLayout (changed, all);
1027         }
1028     }
1029 }
1030 
1031 void moveAbove (GtkWidget* child, GtkWidget* sibling) {
1032     if (child is sibling) return;
1033     auto parentHandle = parentingHandle ();
1034     auto fixed = cast(GtkFixed*)parentHandle;
1035     GList* children = fixed.children;
1036     if (children is null) return;
1037     void* data;
1038     GtkWidget* widget;
1039     void* childData;
1040     GList* childLink, siblingLink;
1041     GList* temp = children;
1042     while (temp !is null) {
1043         data = temp.data;
1044         widget = *cast(GtkWidget**) data;
1045         if (child is widget) {
1046             childLink = temp;
1047             childData = data;
1048         } else if (sibling is widget) {
1049             siblingLink = temp;
1050         }
1051         if (childData !is null && (sibling is null || siblingLink !is null)) break;
1052         temp = cast(GList*)OS.g_list_next (temp);
1053     }
1054     children = OS.g_list_remove_link (children, childLink);
1055     if (siblingLink is null || siblingLink.prev is null) {
1056         OS.g_list_free_1 (childLink);
1057         children = OS.g_list_prepend (children, childData);
1058     } else {
1059         temp = siblingLink.prev;
1060         childLink.prev =  temp;
1061         temp.next = childLink;
1062         childLink.next = siblingLink;
1063         siblingLink.prev = childLink;
1064     }
1065     fixed.children = children;
1066     parentHandle = cast(GtkWidget*)fixed;
1067 }
1068 
1069 alias Scrollable.moveBelow moveBelow;
1070 void moveBelow (GtkWidget* child, GtkWidget* sibling) {
1071     if (child is sibling) return;
1072     auto parentHandle = parentingHandle ();
1073     if (sibling is null && cast(GtkWidget*)parentHandle is cast(GtkWidget*)fixedHandle) {
1074         moveAbove (child, scrolledHandle !is null  ? cast(GtkWidget*)scrolledHandle : handle);
1075         return;
1076     }
1077     auto fixed = cast(GtkFixed*)parentHandle;
1078     GList* children = fixed.children;
1079     if (children is null) return;
1080     void* data;
1081     GtkWidget* widget;
1082     void* childData;
1083     GList* childLink;
1084     GList* siblingLink;
1085     GList* temp = children;
1086     while (temp !is null) {
1087         data = temp.data;
1088         widget = *cast(GtkWidget**) temp.data;
1089         if (child is widget) {
1090             childLink = temp;
1091             childData = data;
1092         } else if (sibling is widget) {
1093             siblingLink = temp;
1094         }
1095         if (childData !is null && (sibling is null || siblingLink !is null)) break;
1096         temp = OS.g_list_next(temp);
1097     }
1098     children = OS.g_list_remove_link (children, childLink);
1099     if (siblingLink is null || OS.g_list_next(siblingLink) is null) {
1100         OS.g_list_free_1 (childLink);
1101         children = OS.g_list_append (children, childData);
1102     } else {
1103         temp = OS.g_list_next( siblingLink );
1104         OS.g_list_set_next (childLink, temp);
1105         OS.g_list_set_previous (temp, childLink);
1106         OS.g_list_set_previous (childLink, siblingLink);
1107         OS.g_list_set_next (siblingLink, childLink);
1108     }
1109     fixed.children = children;
1110     parentHandle = cast(GtkWidget*)fixed;
1111 }
1112 
1113 override
1114 void moveChildren(int oldWidth) {
1115     Control[] children = _getChildren ();
1116     for (int i = 0; i < children.length; i++) {
1117         Control child = children[i];
1118         auto topHandle = child.topHandle ();
1119         int x = OS.GTK_WIDGET_X (topHandle);
1120         int y = OS.GTK_WIDGET_Y (topHandle);
1121         int controlWidth = (child.state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle);
1122         x = oldWidth - controlWidth - x;
1123         int clientWidth = getClientWidth ();
1124         x = clientWidth - controlWidth - x;
1125         if (child.enableWindow !is null) {
1126             OS.gdk_window_move (child.enableWindow, x, y);
1127         }
1128         child.moveHandle (x, y);
1129         /*
1130         * Cause a size allocation this widget's topHandle.  Note that
1131         * all calls to gtk_widget_size_allocate() must be preceded by
1132         * a call to gtk_widget_size_request().
1133         */
1134         GtkRequisition requisition;
1135         gtk_widget_size_request (topHandle, &requisition);
1136         GtkAllocation allocation;
1137         allocation.x = x;
1138         allocation.y = y;
1139         allocation.width = OS.GTK_WIDGET_WIDTH (topHandle);
1140         allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle);
1141         OS.gtk_widget_size_allocate (topHandle, &allocation);
1142         Control control = child.findBackgroundControl ();
1143         if (control !is null && control.backgroundImage !is null) {
1144             if (child.isVisible ()) child.redrawWidget (0, 0, 0, 0, true, true, true);
1145         }
1146     }
1147 }
1148 
1149 Point minimumSize (int wHint, int hHint, bool changed) {
1150     Control [] children = _getChildren ();
1151     int width = 0, height = 0;
1152     for (int i=0; i<children.length; i++) {
1153         Rectangle rect = children [i].getBounds ();
1154         width = Math.max (width, rect.x + rect.width);
1155         height = Math.max (height, rect.y + rect.height);
1156     }
1157     return new Point (width, height);
1158 }
1159 
1160 GtkWidget* parentingHandle () {
1161     if ((state & CANVAS) !is 0) return handle;
1162     return fixedHandle !is null ? fixedHandle : handle;
1163 }
1164 
1165 override void printWidget (GC gc, GdkDrawable* drawable, int depth, int x, int y) {
1166     Region oldClip = new Region (gc.getDevice ());
1167     Region newClip = new Region (gc.getDevice ());
1168     gc.getClipping (oldClip);
1169     Rectangle rect = getBounds ();
1170     newClip.add (oldClip);
1171     newClip.intersect (x, y, rect.width, rect.height);
1172     gc.setClipping (newClip);
1173     super.printWidget (gc, drawable, depth, x, y);
1174     Rectangle clientRect = getClientArea ();
1175     Point pt = display.map (this, parent, clientRect.x, clientRect.y);
1176     clientRect.x = x + pt.x - rect.x;
1177     clientRect.y = y + pt.y - rect.y;
1178     newClip.intersect (clientRect);
1179     gc.setClipping (newClip);
1180     Control [] children = _getChildren ();
1181     for (ptrdiff_t i=cast(ptrdiff_t) (children.length)-1; i>=0; --i) {
1182         Control child = children [i];
1183         if (child.getVisible ()) {
1184             Point location = child.getLocation ();
1185             child.printWidget (gc, drawable, depth, x + location.x, y + location.y);
1186         }
1187     }
1188     gc.setClipping (oldClip);
1189     oldClip.dispose ();
1190     newClip.dispose ();
1191 }
1192 
1193 override void redrawChildren () {
1194     super.redrawChildren ();
1195     Control [] children = _getChildren ();
1196     for (int i = 0; i < children.length; i++) {
1197         Control child = children [i];
1198         if ((child.state & PARENT_BACKGROUND) !is 0) {
1199             child.redrawWidget (0, 0, 0, 0, true, false, true);
1200             child.redrawChildren ();
1201         }
1202     }
1203 }
1204 
1205 override void register () {
1206     super.register ();
1207     if (socketHandle !is null) display.addWidget (socketHandle, this);
1208 }
1209 
1210 override void releaseChildren (bool destroy) {
1211     Control [] children = _getChildren ();
1212     for (int i=0; i<children.length; i++) {
1213         Control child = children [i];
1214         if (child !is null && !child.isDisposed ()) {
1215             child.release (false);
1216         }
1217     }
1218     super.releaseChildren (destroy);
1219 }
1220 
1221 override void releaseHandle () {
1222     super.releaseHandle ();
1223     socketHandle = null;
1224     embeddedHandle = 0;
1225 }
1226 
1227 override void releaseWidget () {
1228     super.releaseWidget ();
1229     if (imHandle_ !is null) OS.g_object_unref (imHandle_);
1230     imHandle_ = null;
1231     layout_ = null;
1232     tabList = null;
1233 }
1234 
1235 void removeControl (Control control) {
1236     fixTabList (control);
1237 }
1238 
1239 override void resizeHandle (int width, int height) {
1240     super.resizeHandle (width, height);
1241     if (socketHandle !is null) OS.gtk_widget_set_size_request (socketHandle, width, height);
1242 }
1243 
1244 /**
1245  * Sets the background drawing mode to the argument which should
1246  * be one of the following constants defined in class <code>SWT</code>:
1247  * <code>INHERIT_NONE</code>, <code>INHERIT_DEFAULT</code>,
1248  * <code>INHERIT_FORCE</code>.
1249  *
1250  * @param mode the new background mode
1251  *
1252  * @exception SWTException <ul>
1253  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1254  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1255  * </ul>
1256  *
1257  * @see SWT
1258  *
1259  * @since 3.2
1260  */
1261 public void setBackgroundMode (int mode) {
1262     checkWidget ();
1263     backgroundMode = mode;
1264     Control[] children = _getChildren ();
1265     for (int i = 0; i < children.length; i++) {
1266         children [i].updateBackgroundMode ();
1267     }
1268 }
1269 
1270 override int setBounds (int x, int y, int width, int height, bool move, bool resize) {
1271     int result = super.setBounds (x, y, width, height, move, resize);
1272     if ((result & RESIZED) !is 0 && layout_ !is null) {
1273         markLayout (false, false);
1274         updateLayout (false);
1275     }
1276     return result;
1277 }
1278 
1279 override public bool setFocus () {
1280     checkWidget();
1281     Control [] children = _getChildren ();
1282     for (int i=0; i<children.length; i++) {
1283         Control child = children [i];
1284         if (child.getVisible () && child.setFocus ()) return true;
1285     }
1286     return super.setFocus ();
1287 }
1288 
1289 /**
1290  * Sets the layout which is associated with the receiver to be
1291  * the argument which may be null.
1292  *
1293  * @param layout the receiver's new layout or null
1294  *
1295  * @exception SWTException <ul>
1296  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1297  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1298  * </ul>
1299  */
1300 public void setLayout (Layout layout) {
1301     checkWidget();
1302     this.layout_ = layout;
1303 }
1304 
1305 /**
1306  * If the argument is <code>true</code>, causes subsequent layout
1307  * operations in the receiver or any of its children to be ignored.
1308  * No layout of any kind can occur in the receiver or any of its
1309  * children until the flag is set to false.
1310  * Layout operations that occurred while the flag was
1311  * <code>true</code> are remembered and when the flag is set to
1312  * <code>false</code>, the layout operations are performed in an
1313  * optimized manner.  Nested calls to this method are stacked.
1314  *
1315  * @param defer the new defer state
1316  *
1317  * @exception SWTException <ul>
1318  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1319  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1320  * </ul>
1321  *
1322  * @see #layout(bool)
1323  * @see #layout(Control[])
1324  *
1325  * @since 3.1
1326  */
1327 public void setLayoutDeferred (bool defer) {
1328     if (!defer) {
1329         if (--layoutCount is 0) {
1330             if ((state & LAYOUT_CHILD) !is 0 || (state & LAYOUT_NEEDED) !is 0) {
1331                 updateLayout (true);
1332             }
1333         }
1334     } else {
1335         layoutCount++;
1336     }
1337 }
1338 
1339 override bool setScrollBarVisible (ScrollBar bar, bool visible) {
1340     bool changed = super.setScrollBarVisible (bar, visible);
1341     if (changed && layout_ !is null) {
1342         markLayout (false, false);
1343         updateLayout (false);
1344     }
1345     return changed;
1346 }
1347 
1348 override bool setTabGroupFocus (bool next) {
1349     if (isTabItem ()) return setTabItemFocus (next);
1350     bool takeFocus = (style & SWT.NO_FOCUS) is 0;
1351     if ((state & CANVAS) !is 0) takeFocus = hooksKeys ();
1352     if (socketHandle !is null) takeFocus = true;
1353     if (takeFocus  && setTabItemFocus (next)) return true;
1354     Control [] children = _getChildren ();
1355     for (int i=0; i<children.length; i++) {
1356         Control child = children [i];
1357         if (child.isTabItem () && child.setTabItemFocus (next)) return true;
1358     }
1359     return false;
1360 }
1361 
1362 override bool setTabItemFocus (bool next) {
1363     if (!super.setTabItemFocus (next)) return false;
1364     if (socketHandle !is null) {
1365         int direction = next ? OS.GTK_DIR_TAB_FORWARD : OS.GTK_DIR_TAB_BACKWARD;
1366         OS.GTK_WIDGET_UNSET_FLAGS (socketHandle, OS.GTK_HAS_FOCUS);
1367         OS.gtk_widget_child_focus (socketHandle, direction);
1368         OS.GTK_WIDGET_SET_FLAGS (socketHandle, OS.GTK_HAS_FOCUS);
1369     }
1370     return true;
1371 }
1372 
1373 /**
1374  * Sets the tabbing order for the specified controls to
1375  * match the order that they occur in the argument list.
1376  *
1377  * @param tabList the ordered list of controls representing the tab order or null
1378  *
1379  * @exception IllegalArgumentException <ul>
1380  *    <li>ERROR_INVALID_ARGUMENT - if a widget in the tabList is null or has been disposed</li>
1381  *    <li>ERROR_INVALID_PARENT - if widget in the tabList is not in the same widget tree</li>
1382  * </ul>
1383  * @exception SWTException <ul>
1384  *    <li>ERROR_WIDGET_DISPOSED - if the receiver has been disposed</li>
1385  *    <li>ERROR_THREAD_INVALID_ACCESS - if not called from the thread that created the receiver</li>
1386  * </ul>
1387  */
1388 public void setTabList (Control [] tabList) {
1389     checkWidget ();
1390     if (tabList !is null) {
1391         for (int i=0; i<tabList.length; i++) {
1392             Control control = tabList [i];
1393             if (control is null) error (SWT.ERROR_INVALID_ARGUMENT);
1394             if (control.isDisposed ()) error (SWT.ERROR_INVALID_ARGUMENT);
1395             if (control.parent !is this) error (SWT.ERROR_INVALID_PARENT);
1396         }
1397         Control [] newList = new Control [tabList.length];
1398         System.arraycopy (tabList, 0, newList, 0, tabList.length);
1399         tabList = newList;
1400     }
1401     this.tabList = tabList;
1402 }
1403 
1404 override void showWidget () {
1405     super.showWidget ();
1406     if (socketHandle !is null) {
1407         OS.gtk_widget_show (socketHandle);
1408         embeddedHandle = OS.gtk_socket_get_id (cast(GtkSocket*)socketHandle);
1409     }
1410     if (scrolledHandle is null) fixStyle (handle);
1411 }
1412 
1413 override bool translateMnemonic (Event event, Control control) {
1414     if (super.translateMnemonic (event, control)) return true;
1415     if (control !is null) {
1416         Control [] children = _getChildren ();
1417         for (int i=0; i<children.length; i++) {
1418             Control child = children [i];
1419             if (child.translateMnemonic (event, control)) return true;
1420         }
1421     }
1422     return false;
1423 }
1424 
1425 override int traversalCode(int key, GdkEventKey* event) {
1426     if ((state & CANVAS) !is 0) {
1427         if ((style & SWT.NO_FOCUS) !is 0) return 0;
1428         if (hooksKeys ()) return 0;
1429     }
1430     return super.traversalCode (key, event);
1431 }
1432 
1433 override bool translateTraversal (GdkEventKey* keyEvent) {
1434     if (socketHandle !is null) return false;
1435     return super.translateTraversal (keyEvent);
1436 }
1437 
1438 override void updateBackgroundMode () {
1439     super.updateBackgroundMode ();
1440     Control [] children = _getChildren ();
1441     for (int i = 0; i < children.length; i++) {
1442         children [i].updateBackgroundMode ();
1443     }
1444 }
1445 
1446 override void updateLayout (bool all) {
1447     Composite parent = findDeferredControl ();
1448     if (parent !is null) {
1449         parent.state |= LAYOUT_CHILD;
1450         return;
1451     }
1452     if ((state & LAYOUT_NEEDED) !is 0) {
1453         bool changed = (state & LAYOUT_CHANGED) !is 0;
1454         state &= ~(LAYOUT_NEEDED | LAYOUT_CHANGED);
1455         layout_.layout (this, changed);
1456     }
1457     if (all) {
1458         state &= ~LAYOUT_CHILD;
1459         Control [] children = _getChildren ();
1460         for (int i=0; i<children.length; i++) {
1461             children [i].updateLayout (all);
1462         }
1463     }
1464 }
1465 }