diff dwt/widgets/Control.d @ 240:ce446666f5a2

Update to SWT 3.4M7
author Frank Benoit <benoit@tionex.de>
date Mon, 12 May 2008 19:13:01 +0200
parents 380bad9f6852
children 5a30aa9820f3
line wrap: on
line diff
--- a/dwt/widgets/Control.d	Mon May 12 15:36:37 2008 +0200
+++ b/dwt/widgets/Control.d	Mon May 12 19:13:01 2008 +0200
@@ -39,6 +39,7 @@
 import dwt.graphics.Image;
 import dwt.graphics.Point;
 import dwt.graphics.Rectangle;
+import dwt.graphics.Region;
 import dwt.internal.Converter;
 import dwt.internal.DWTEventListener;
 import dwt.internal.accessibility.gtk.ATK;
@@ -96,6 +97,7 @@
     Menu menu;
     Image backgroundImage;
     Font font;
+    Region region;
     String toolTipText;
     Object layoutData;
     Accessible accessible;
@@ -137,8 +139,8 @@
     createWidget (0);
 }
 
-PangoFontDescription* defaultFont () {
-    return display.getSystemFont ().handle;
+Font defaultFont () {
+    return display.getSystemFont ();
 }
 
 override void deregister () {
@@ -153,6 +155,7 @@
     auto window = OS.GTK_WIDGET_WINDOW (paintHandle);
     if (window is null) return false;
     int orientation = vertical ? OS.GTK_ORIENTATION_HORIZONTAL : OS.GTK_ORIENTATION_VERTICAL;
+    if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - width - x;
     char dummy;
     OS.gtk_paint_handle (OS.gtk_widget_get_style (paintHandle), window, OS.GTK_STATE_NORMAL, OS.GTK_SHADOW_OUT, null, paintHandle, &dummy, x, y, width, height, orientation);
     return true;
@@ -241,8 +244,7 @@
 
     /* Connect the mouse signals */
     auto eventHandle = eventHandle ();
-    int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK |
-        OS.GDK_BUTTON_RELEASE_MASK;
+    int eventMask = OS.GDK_POINTER_MOTION_MASK | OS.GDK_BUTTON_PRESS_MASK | OS.GDK_BUTTON_RELEASE_MASK;
     OS.gtk_widget_add_events (eventHandle, eventMask);
     OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_PRESS_EVENT], 0, display.closures [BUTTON_PRESS_EVENT], false);
     OS.g_signal_connect_closure_by_id (eventHandle, display.signalIds [BUTTON_RELEASE_EVENT], 0, display.closures [BUTTON_RELEASE_EVENT], false);
@@ -296,8 +298,8 @@
 
     OS.g_signal_connect_closure_by_id (paintHandle, display.signalIds [STYLE_SET], 0, display.closures [STYLE_SET], false);
 
-    auto topHandle = topHandle ();
-    OS.g_signal_connect_closure_by_id (topHandle, display.signalIds [MAP], 0, display.closures [MAP], true);
+    auto topHandle_ = topHandle ();
+    OS.g_signal_connect_closure_by_id (topHandle_, display.signalIds [MAP], 0, display.closures [MAP], true);
 }
 
 override int /*long*/ hoverProc (GtkWidget* widget) {
@@ -315,9 +317,9 @@
 }
 
 GtkWidget* paintHandle () {
-    auto topHandle = topHandle ();
+    auto topHandle_ = topHandle ();
     auto paintHandle = handle;
-    while (paintHandle !is topHandle) {
+    while (paintHandle !is topHandle_) {
         if ((OS.GTK_WIDGET_FLAGS (paintHandle) & OS.GTK_NO_WINDOW) is 0) break;
         paintHandle = OS.gtk_widget_get_parent (paintHandle);
     }
@@ -330,6 +332,91 @@
     return OS.GTK_WIDGET_WINDOW (paintHandle);
 }
 
+public bool print (GC gc) {
+    checkWidget ();
+    if (gc is null) error (DWT.ERROR_NULL_ARGUMENT);
+    if (gc.isDisposed ()) error (DWT.ERROR_INVALID_ARGUMENT);
+    auto topHandle_ = topHandle ();
+    OS.gtk_widget_realize (topHandle_);
+    auto window = OS.GTK_WIDGET_WINDOW (topHandle_);
+    GCData data = gc.getGCData ();
+    OS.gdk_window_process_updates (window, cast(int)true);
+    printWidget (gc, data.drawable, OS.gdk_drawable_get_depth (data.drawable), 0, 0);
+    return true;
+}
+
+void printWidget (GC gc, GdkDrawable* drawable, int depth, int x, int y) {
+    bool obscured = (state & OBSCURED) !is 0;
+    state &= ~OBSCURED;
+    auto topHandle_ = topHandle ();
+    auto window = OS.GTK_WIDGET_WINDOW (topHandle_);
+    printWindow (true, this, gc.handle, drawable, depth, window, x, y);
+    if (obscured) state |= OBSCURED;
+}
+
+void printWindow (bool first, Control control, GdkGC* gc, GdkDrawable* drawable, int depth, GdkDrawable* window, int x, int y) {
+    if (OS.gdk_drawable_get_depth (window) !is depth) return;
+    GdkRectangle rect;
+    int width, height;
+    OS.gdk_drawable_get_size (window, &width, &height);
+    rect.width = width;
+    rect.height = height;
+    OS.gdk_window_begin_paint_rect (window, &rect);
+    GdkDrawable* real_drawable;
+    int x_offset, y_offset;
+    OS.gdk_window_get_internal_paint_info (window, &real_drawable, &x_offset, &y_offset);
+    void* userData;
+    OS.gdk_window_get_user_data (window, &userData);
+    if (userData !is null) {
+        GdkEventExpose* event = cast(GdkEventExpose*) OS.gdk_event_new (OS.GDK_EXPOSE);
+        event.type = OS.GDK_EXPOSE;
+        event.window = cast(GdkDrawable*)OS.g_object_ref (window);
+        event.area.width = rect.width;
+        event.area.height = rect.height;
+        event.region = OS.gdk_region_rectangle (&rect);
+        OS.gtk_widget_send_expose (userData, cast(GdkEvent*)event);
+        OS.gdk_event_free (cast(GdkEvent*)event);
+    }
+    int srcX = x_offset, srcY = y_offset;
+    int destX = x, destY = y, destWidth = width, destHeight = height;
+    if (!first) {
+        int cX, cY;
+        OS.gdk_window_get_position (window, &cX, &cY);
+        auto parentWindow = OS.gdk_window_get_parent (window);
+        int pW, pH;
+        OS.gdk_drawable_get_size (parentWindow, &pW, &pH);
+        srcX = x_offset - cX;
+        srcY = y_offset - cY;
+        destX = x - cX;
+        destY = y - cY;
+        destWidth = Math.min (cX + width, pW);
+        destHeight = Math.min (cY + height, pH);
+    }
+    OS.gdk_draw_drawable (drawable, gc, real_drawable, srcX, srcY, destX, destY, destWidth, destHeight);
+    OS.gdk_window_end_paint (window);
+    auto children = OS.gdk_window_get_children (window);
+    if (children !is null) {
+        auto windows = children;
+        while (windows !is null) {
+            auto child = cast(GdkDrawable*) OS.g_list_data (windows);
+            if (OS.gdk_window_is_visible (child)) {
+                void* data;
+                OS.gdk_window_get_user_data (child, &data);
+                if (data !is null) {
+                    Widget widget = display.findWidget ( cast(GtkWidget*) data);
+                    if (widget is null || widget is control) {
+                        int x_pos, y_pos;
+                        OS.gdk_window_get_position (child, &x_pos, &y_pos);
+                        printWindow (false, control, gc, drawable, depth, child, x + x_pos, y + y_pos);
+                    }
+                }
+            }
+            windows = OS.g_list_next (windows);
+        }
+        OS.g_list_free (children);
+    }
+}
+
 /**
  * Returns the preferred size of the receiver.
  * <p>
@@ -423,6 +510,10 @@
     if (getBorderWidth () is 0) style &= ~DWT.BORDER;
 }
 
+void checkMirrored () {
+    if ((style & DWT.RIGHT_TO_LEFT) !is 0) style |= DWT.MIRRORED;
+}
+
 GtkStyle* childStyle () {
     return parent.childStyle ();
 }
@@ -438,6 +529,7 @@
     setInitialBounds ();
     setZOrder (null, false, false);
     setRelations ();
+    checkMirrored ();
     checkBorder ();
 }
 
@@ -508,15 +600,15 @@
     * topHandle.  Note that all calls to gtk_widget_size_allocate()
     * must be preceded by a call to gtk_widget_size_request().
     */
-    auto topHandle = topHandle ();
+    auto topHandle_ = topHandle ();
     GtkRequisition requisition;
-    gtk_widget_size_request (topHandle, &requisition);
+    gtk_widget_size_request (topHandle_, &requisition);
     GtkAllocation allocation;
-    allocation.x = OS.GTK_WIDGET_X (topHandle);
-    allocation.y = OS.GTK_WIDGET_Y (topHandle);
-    allocation.width = OS.GTK_WIDGET_WIDTH (topHandle);
-    allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle);
-    OS.gtk_widget_size_allocate (topHandle, &allocation);
+    allocation.x = OS.GTK_WIDGET_X (topHandle_);
+    allocation.y = OS.GTK_WIDGET_Y (topHandle_);
+    allocation.width = OS.GTK_WIDGET_WIDTH (topHandle_);
+    allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle_);
+    OS.gtk_widget_size_allocate (topHandle_, &allocation);
 }
 
 /**
@@ -559,11 +651,12 @@
  */
 public Rectangle getBounds () {
     checkWidget();
-    auto topHandle = topHandle ();
-    int x = OS.GTK_WIDGET_X (topHandle);
-    int y = OS.GTK_WIDGET_Y (topHandle);
-    int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle);
-    int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle);
+    auto topHandle_ = topHandle ();
+    int x = OS.GTK_WIDGET_X (topHandle_);
+    int y = OS.GTK_WIDGET_Y (topHandle_);
+    int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_);
+    int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_);
+    if ((parent.style & DWT.MIRRORED) !is 0) x = parent.getClientWidth () - width - x;
     return new Rectangle (x, y, width, height);
 }
 
@@ -623,8 +716,18 @@
     /* Do nothing */
 }
 
+override void modifyStyle (GtkWidget* handle, GtkRcStyle* style) {
+    super.modifyStyle(handle, style);
+    /*
+    * Bug in GTK.  When changing the style of a control that
+    * has had a region set on it, the region is lost.  The
+    * fix is to set the region again.
+    */
+    if (region !is null) OS.gdk_window_shape_combine_region (OS.GTK_WIDGET_WINDOW (topHandle ()), region.handle, 0, 0);
+}
+
 void moveHandle (int x, int y) {
-    auto topHandle = topHandle ();
+    auto topHandle_ = topHandle ();
     auto parentHandle = parent.parentingHandle ();
     /*
     * Feature in GTK.  Calling gtk_fixed_move() to move a child causes
@@ -636,24 +739,38 @@
     */
     int flags = OS.GTK_WIDGET_FLAGS (parentHandle);
     OS.GTK_WIDGET_UNSET_FLAGS (parentHandle, OS.GTK_VISIBLE);
-    OS.gtk_fixed_move (cast(GtkFixed*)parentHandle, topHandle, x, y);
+    OS.gtk_fixed_move (cast(GtkFixed*)parentHandle, topHandle_, x, y);
     if ((flags & OS.GTK_VISIBLE) !is 0) {
         OS.GTK_WIDGET_SET_FLAGS (parentHandle, OS.GTK_VISIBLE);
     }
 }
 
 void resizeHandle (int width, int height) {
-    auto topHandle = topHandle ();
-    OS.gtk_widget_set_size_request (topHandle, width, height);
-    if (topHandle !is handle) OS.gtk_widget_set_size_request (handle, width, height);
+    auto topHandle_ = topHandle ();
+    OS.gtk_widget_set_size_request (topHandle_, width, height);
+    if (topHandle_ !is handle) OS.gtk_widget_set_size_request (handle, width, height);
 }
 
 int setBounds (int x, int y, int width, int height, bool move, bool resize) {
-    auto topHandle = topHandle ();
+    auto topHandle_ = topHandle ();
+    bool sendMove = move;
+    if ((parent.style & DWT.MIRRORED) !is 0) {
+        int clientWidth = parent.getClientWidth ();
+        int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_);
+        int oldX = clientWidth - oldWidth - OS.GTK_WIDGET_X (topHandle_);
+        if (move) {
+            sendMove &= x !is oldX;
+            x = clientWidth - (resize ? width : oldWidth) - x;
+        } else {
+            move = true;
+            x = clientWidth - (resize ? width : oldWidth) - oldX;
+            y = OS.GTK_WIDGET_Y (topHandle_);
+        }
+    }
     bool sameOrigin = true, sameExtent = true;
     if (move) {
-        int oldX = OS.GTK_WIDGET_X (topHandle);
-        int oldY = OS.GTK_WIDGET_Y (topHandle);
+        int oldX = OS.GTK_WIDGET_X (topHandle_);
+        int oldY = OS.GTK_WIDGET_Y (topHandle_);
         sameOrigin = x is oldX && y is oldY;
         if (!sameOrigin) {
             if (enableWindow !is null) {
@@ -662,10 +779,12 @@
             moveHandle (x, y);
         }
     }
+    int clientWidth = 0;
     if (resize) {
-        int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle);
-        int oldHeight = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle);
+        int oldWidth = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_);
+        int oldHeight = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_);
         sameExtent = width is oldWidth && height is oldHeight;
+        if (!sameExtent && (style & DWT.MIRRORED) !is 0) clientWidth = getClientWidth ();
         if (!sameExtent && !(width is 0 && height is 0)) {
             int newWidth = Math.max (1, width);
             int newHeight = Math.max (1, height);
@@ -685,23 +804,23 @@
         * a call to gtk_widget_size_request().
         */
         GtkRequisition requisition;
-        gtk_widget_size_request (topHandle, &requisition);
+        gtk_widget_size_request (topHandle_, &requisition);
         GtkAllocation allocation;
         if (move) {
             allocation.x = x;
             allocation.y = y;
         } else {
-            allocation.x = OS.GTK_WIDGET_X (topHandle);
-            allocation.y = OS.GTK_WIDGET_Y (topHandle);
+            allocation.x = OS.GTK_WIDGET_X (topHandle_);
+            allocation.y = OS.GTK_WIDGET_Y (topHandle_);
         }
         if (resize) {
             allocation.width = width;
             allocation.height = height;
         } else {
-            allocation.width = OS.GTK_WIDGET_WIDTH (topHandle);
-            allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle);
+            allocation.width = OS.GTK_WIDGET_WIDTH (topHandle_);
+            allocation.height = OS.GTK_WIDGET_HEIGHT (topHandle_);
         }
-        OS.gtk_widget_size_allocate (topHandle, &allocation);
+        OS.gtk_widget_size_allocate (topHandle_, &allocation);
     }
     /*
     * Bug in GTK.  Widgets cannot be sized smaller than 1x1.
@@ -715,15 +834,16 @@
             if (enableWindow !is null) {
                 OS.gdk_window_hide (enableWindow);
             }
-            OS.gtk_widget_hide (topHandle);
+            OS.gtk_widget_hide (topHandle_);
         } else {
             if ((state & HIDDEN) is 0) {
                 if (enableWindow !is null) {
                     OS.gdk_window_show_unraised (enableWindow);
                 }
-                OS.gtk_widget_show (topHandle);
+                OS.gtk_widget_show (topHandle_);
             }
         }
+        if ((style & DWT.MIRRORED) !is 0) moveChildren (clientWidth);
     }
     int result = 0;
     if (move && !sameOrigin) {
@@ -731,7 +851,7 @@
         if (control !is null && control.backgroundImage !is null) {
             if (isVisible ()) redrawWidget (0, 0, 0, 0, true, true, true);
         }
-        sendEvent (DWT.Move);
+        if (sendMove) sendEvent (DWT.Move);
         result |= MOVED;
     }
     if (resize && !sameExtent) {
@@ -756,9 +876,13 @@
  */
 public Point getLocation () {
     checkWidget();
-    auto topHandle = topHandle ();
-    int x = OS.GTK_WIDGET_X (topHandle);
-    int y = OS.GTK_WIDGET_Y (topHandle);
+    auto topHandle_ = topHandle ();
+    int x = OS.GTK_WIDGET_X (topHandle_);
+    int y = OS.GTK_WIDGET_Y (topHandle_);
+    if ((parent.style & DWT.MIRRORED) !is 0) {
+        int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_);
+        x = parent.getClientWidth () - width - x;
+    }
     return new Point (x, y);
 }
 
@@ -817,9 +941,9 @@
  */
 public Point getSize () {
     checkWidget();
-    auto topHandle = topHandle ();
-    int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle);
-    int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle);
+    auto topHandle_ = topHandle ();
+    int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_);
+    int height = (state & ZERO_HEIGHT) !is 0 ? 0 : OS.GTK_WIDGET_HEIGHT (topHandle_);
     return new Point (width, height);
 }
 
@@ -847,6 +971,16 @@
     setBounds (0, 0, Math.max (0, size.x), Math.max (0, size.y), false, true);
 }
 
+public void setRegion (Region region) {
+    checkWidget ();
+    if ((style & DWT.NO_TRIM) is 0) return;
+    if (region !is null && region.isDisposed()) error (DWT.ERROR_INVALID_ARGUMENT);
+    auto window = OS.GTK_WIDGET_WINDOW (topHandle ());
+    auto shape_region = (region is null) ? null : region.handle;
+    OS.gdk_window_shape_combine_region (window, shape_region, 0, 0);
+    this.region = region;
+}
+
 void setRelations () {
     auto parentHandle = parent.parentingHandle ();
     auto list = OS.gtk_container_get_children (cast(GtkContainer*)parentHandle);
@@ -899,6 +1033,10 @@
     return true;
 }
 
+bool isFocusHandle (GtkWidget* widget) {
+    return widget is focusHandle ();
+}
+
 /**
  * Moves the receiver above the specified control in the
  * drawing order. If the argument is null, then the receiver
@@ -957,6 +1095,9 @@
     setZOrder (control, false, true);
 }
 
+void moveChildren (int oldWidth) {
+}
+
 /**
  * Causes the receiver to be resized to its preferred size.
  * For a composite, this involves computing the preferred size
@@ -1034,7 +1175,10 @@
     auto window = eventWindow ();
     int origin_x, origin_y;
     OS.gdk_window_get_origin (window, &origin_x, &origin_y);
-    return new Point (x - origin_x , y - origin_y );
+    x -= origin_x ;
+    y -= origin_y ;
+    if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - x;
+    return new Point (x, y);
 }
 
 /**
@@ -1080,7 +1224,10 @@
     auto window = eventWindow ();
     int origin_x, origin_y;
     OS.gdk_window_get_origin (window, &origin_x, &origin_y);
-    return new Point (origin_x + x, origin_y + y);
+    if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - x;
+    x += origin_x ;
+    y += origin_y ;
+    return new Point (x, y);
 }
 
 /**
@@ -1939,6 +2086,9 @@
     return 0;
 }
 
+void fixModal(GtkWidget* group, GtkWidget* modalGroup) {
+}
+
 /**
  * Forces the receiver to have the <em>keyboard focus</em>, causing
  * all keyboard events to be delivered to it.
@@ -2051,6 +2201,10 @@
     return 0;
 }
 
+int getClientWidth () {
+    return 0;
+}
+
 /**
  * Returns the receiver's cursor, or null if it has not been set.
  * <p>
@@ -2120,8 +2274,7 @@
  */
 public Font getFont () {
     checkWidget();
-    if (font !is null) return font;
-    return Font.gtk_new (display, defaultFont ());
+    return font !is null ? font : defaultFont ();
 }
 
 PangoFontDescription* getFontDescription () {
@@ -2278,6 +2431,11 @@
     return result;
 }
 
+public Region getRegion () {
+    checkWidget ();
+    return region;
+}
+
 /**
  * Returns the receiver's shell. For all controls other than
  * shells, this simply returns the control's nearest ancestor
@@ -2341,6 +2499,7 @@
 
 override int /*long*/ gtk_button_press_event (GtkWidget* widget, GdkEventButton* gdkEvent) {
     if (gdkEvent.type is OS.GDK_3BUTTON_PRESS) return 0;
+
     /*
     * When a shell is created with DWT.ON_TOP and DWT.NO_FOCUS,
     * do not activate the shell when the user clicks on the
@@ -2427,6 +2586,21 @@
 }
 
 override int /*long*/ gtk_enter_notify_event (GtkWidget*  widget, GdkEventCrossing* gdkEvent) {
+    if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) {
+        /*
+         * Feature in GTK. Children of a shell will inherit and display the shell's
+         * tooltip if they do not have a tooltip of their own. The fix is to use the
+         * new tooltip API in GTK 2.12 to null the shell's tooltip when the control
+         * being entered does not have any tooltip text set.
+         */
+        char* buffer = null;
+        if (toolTipText !is null && toolTipText.length !is 0) {
+            char [] chars = fixMnemonic (toolTipText, false);
+            buffer = tango.stdc.stringz.toStringz(chars);
+        }
+        auto toolHandle = getShell().handle;
+        OS.gtk_widget_set_tooltip_text (toolHandle, buffer);
+    }
     if (display.currentControl is this) return 0;
     if (gdkEvent.mode !is OS.GDK_CROSSING_NORMAL && gdkEvent.mode !is OS.GDK_CROSSING_UNGRAB) return 0;
     if ((gdkEvent.state & (OS.GDK_BUTTON1_MASK | OS.GDK_BUTTON2_MASK | OS.GDK_BUTTON3_MASK)) !is 0) return 0;
@@ -2459,7 +2633,7 @@
             break;
         }
         case OS.GDK_FOCUS_CHANGE: {
-            if (widget !is focusHandle ()) break;
+            if (!isFocusHandle (widget)) break;
             GdkEventFocus* gdkEventFocus = cast(GdkEventFocus*)gdkEvent;
 
             /*
@@ -2503,6 +2677,7 @@
     event.y = gdkEvent.area.y;
     event.width = gdkEvent.area.width;
     event.height = gdkEvent.area.height;
+    if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.width - event.x;
     GCData data = new GCData ();
     data.damageRgn = gdkEvent.region;
     GC gc = event.gc = GC.gtk_new (this, data);
@@ -2733,6 +2908,10 @@
         int mask = DWT.LEFT_TO_RIGHT | DWT.RIGHT_TO_LEFT;
         if ((data.style & mask) is 0) {
             data.style |= style & (mask | DWT.MIRRORED);
+        } else {
+            if ((data.style & DWT.RIGHT_TO_LEFT) !is 0) {
+                data.style |= DWT.MIRRORED;
+            }
         }
         data.drawable = cast(GdkDrawable*)window;
         data.device = display;
@@ -2740,7 +2919,7 @@
         Control control = findBackgroundControl ();
         if (control is null) control = this;
         data.background = control.getBackgroundColor ();
-        data.font = font !is null ? font.handle : defaultFont ();
+        data.font = font !is null ? font : defaultFont ();
     }
     return gdkGC;
 }
@@ -2969,6 +3148,7 @@
 public void redraw (int x, int y, int width, int height, bool all) {
     checkWidget();
     if (!OS.GTK_WIDGET_VISIBLE (topHandle ())) return;
+    if ((style & DWT.MIRRORED) !is 0) x = getClientWidth () - width - x;
     redrawWidget (x, y, width, height, false, all, false);
 }
 
@@ -3046,6 +3226,7 @@
     toolTipText = null;
     layoutData = null;
     accessible = null;
+    region = null;
 }
 
 bool sendDragEvent (int button, int stateMask, int x, int y, bool isStateMask) {
@@ -3053,6 +3234,7 @@
     event.button = button;
     event.x = x;
     event.y = y;
+    if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.x;
     if (isStateMask) {
         event.stateMask = stateMask;
     } else {
@@ -3129,6 +3311,7 @@
         event.x = cast(int)x - origin_x;
         event.y = cast(int)y - origin_y;
     }
+    if ((style & DWT.MIRRORED) !is 0) event.x = getClientWidth () - event.x;
     setInputState (event, state);
     if (send) {
         sendEvent (type, event);
@@ -3207,7 +3390,7 @@
     int flags = OS.gtk_rc_style_get_color_flags (style, index);
     flags = (color is null) ? flags & ~OS.GTK_RC_BG : flags | OS.GTK_RC_BG;
     OS.gtk_rc_style_set_color_flags (style, index, flags);
-    OS.gtk_widget_modify_style (handle, style);
+    modifyStyle (handle, style);
 }
 
 void setBackgroundColor (GdkColor* color) {
@@ -3379,8 +3562,8 @@
         }
     } else {
         OS.gtk_widget_realize (handle);
-        auto parentHandle = parent.parentingHandle ();
-        auto window = OS.GTK_WIDGET_WINDOW (parentHandle);
+        auto parentHandle = parent.eventHandle ();
+        auto window = parent.eventWindow();
         Rectangle rect = getBounds ();
         GdkWindowAttr attributes;
         attributes.x = rect.x;
@@ -3392,12 +3575,12 @@
         attributes.window_type = OS.GDK_WINDOW_CHILD;
         enableWindow = OS.gdk_window_new (window, &attributes, OS.GDK_WA_X | OS.GDK_WA_Y);
         if (enableWindow !is null) {
-            auto topHandle = topHandle ();
+            auto topHandle_ = topHandle ();
             OS.gdk_window_set_user_data (enableWindow, parentHandle);
             if (!OS.GDK_WINDOWING_X11 ()) {
                 OS.gdk_window_raise (enableWindow);
             } else {
-                auto topWindow = OS.GTK_WIDGET_WINDOW (topHandle);
+                auto topWindow = OS.GTK_WIDGET_WINDOW (topHandle_);
                 auto xDisplay = OS.gdk_x11_drawable_get_xdisplay (cast(GdkDrawable*)topWindow);
                 auto xWindow = OS.gdk_x11_drawable_get_xid (cast(GdkDrawable*)enableWindow);
                 int xScreen = OS.XDefaultScreen (xDisplay);
@@ -3407,7 +3590,7 @@
                 changes.stack_mode = OS.Above;
                 OS.XReconfigureWMWindow (xDisplay, xWindow, xScreen, flags, &changes);
             }
-            if (OS.GTK_WIDGET_VISIBLE (topHandle)) OS.gdk_window_show_unraised (enableWindow);
+            if (OS.GTK_WIDGET_VISIBLE (topHandle_)) OS.gdk_window_show_unraised (enableWindow);
         }
     }
     if (fixFocus_) fixFocus (control);
@@ -3454,7 +3637,7 @@
     this.font = font;
     PangoFontDescription* fontDesc;
     if (font is null) {
-        fontDesc = defaultFont ();
+        fontDesc = defaultFont ().handle;
     } else {
         if (font.isDisposed ()) DWT.error(DWT.ERROR_INVALID_ARGUMENT);
         fontDesc = font.handle;
@@ -3526,9 +3709,13 @@
         * first sized.  The fix is to set the value to (0, 0) as
         * expected by DWT.
         */
-        auto topHandle = topHandle ();
-        OS.GTK_WIDGET_SET_X (topHandle, 0);
-        OS.GTK_WIDGET_SET_Y (topHandle, 0);
+        auto topHandle_ = topHandle ();
+        if ((parent.style & DWT.MIRRORED) !is 0) {
+            OS.GTK_WIDGET_SET_X (topHandle_, parent.getClientWidth ());
+        } else {
+            OS.GTK_WIDGET_SET_X (topHandle_, 0);
+        }
+        OS.GTK_WIDGET_SET_Y (topHandle_, 0);
     } else {
         resizeHandle (1, 1);
         forceResize ();
@@ -3603,6 +3790,16 @@
     if (parent.isDisposed()) DWT.error (DWT.ERROR_INVALID_ARGUMENT);
     if (this.parent is parent) return true;
     if (!isReparentable ()) return false;
+    auto topHandle_ = topHandle ();
+    int x = OS.GTK_WIDGET_X (topHandle_);
+    int width = (state & ZERO_WIDTH) !is 0 ? 0 : OS.GTK_WIDGET_WIDTH (topHandle_);
+    if ((this.parent.style & DWT.MIRRORED) !is 0) {
+        x =  this.parent.getClientWidth () - width - x;
+    }
+    if ((parent.style & DWT.MIRRORED) !is 0) {
+        x = parent.getClientWidth () - width - x;
+    }
+    int y = OS.GTK_WIDGET_Y (topHandle_);
     releaseParent ();
     Shell newShell = parent.getShell (), oldShell = getShell ();
     Decorations newDecorations = parent.menuShell (), oldDecorations = menuShell ();
@@ -3612,12 +3809,9 @@
         newDecorations.fixAccelGroup ();
         oldDecorations.fixAccelGroup ();
     }
-    auto topHandle = topHandle ();
     auto newParent = parent.parentingHandle();
-    int x = OS.GTK_WIDGET_X (topHandle);
-    int y = OS.GTK_WIDGET_Y (topHandle);
-    OS.gtk_widget_reparent (topHandle, newParent);
-    OS.gtk_fixed_move (cast(GtkFixed*)newParent, topHandle, x, y);
+    OS.gtk_widget_reparent (topHandle_, newParent);
+    OS.gtk_fixed_move (cast(GtkFixed*)newParent, topHandle_, x, y);
     this.parent = parent;
     setZOrder (null, false, true);
     return true;
@@ -3723,7 +3917,25 @@
 }
 
 void setToolTipText (Shell shell, String newString) {
-    shell.setToolTipText (eventHandle (), newString);
+    if (OS.GTK_VERSION >= OS.buildVERSION (2, 12, 0)) {
+        /*
+        * Feature in GTK.  In order to prevent children widgets
+        * from inheriting their parent's tooltip, the tooltip is
+        * a set on a shell only. In order to force the shell tooltip
+        * to update when a new tip string is set, the existing string
+        * in the tooltip is set to null, followed by running a query.
+        * The real tip text can then be set.
+        *
+        * Note that this will only run if the control for which the
+        * tooltip is being set is the current control (i.e. the control
+        * under the pointer).
+        */
+        if (display.currentControl is this) {
+            shell.setToolTipText (shell.handle, eventHandle (), newString);
+        }
+    } else {
+        shell.setToolTipText (eventHandle (), newString);
+    }
 }
 
 /**
@@ -3745,7 +3957,7 @@
 public void setVisible (bool visible) {
     checkWidget();
     if (((state & HIDDEN) is 0) is visible) return;
-    auto topHandle = topHandle();
+    auto topHandle_ = topHandle();
     if (visible) {
         /*
         * It is possible (but unlikely), that application
@@ -3757,7 +3969,7 @@
         state &= ~HIDDEN;
         if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) is 0) {
             if (enableWindow !is null) OS.gdk_window_show_unraised (enableWindow);
-            OS.gtk_widget_show (topHandle);
+            OS.gtk_widget_show (topHandle_);
         }
     } else {
         /*
@@ -3777,12 +3989,12 @@
         }
         state |= HIDDEN;
         if (fixFocus_) {
-            OS.GTK_WIDGET_UNSET_FLAGS (topHandle, OS.GTK_VISIBLE);
+            OS.GTK_WIDGET_UNSET_FLAGS (topHandle_, OS.GTK_VISIBLE);
             fixFocus (control);
             if (isDisposed ()) return;
-            OS.GTK_WIDGET_SET_FLAGS (topHandle, OS.GTK_VISIBLE);
+            OS.GTK_WIDGET_SET_FLAGS (topHandle_, OS.GTK_VISIBLE);
         }
-        OS.gtk_widget_hide (topHandle);
+        OS.gtk_widget_hide (topHandle_);
         if (isDisposed ()) return;
         if (enableWindow !is null) OS.gdk_window_hide (enableWindow);
         sendEvent (DWT.Hide);
@@ -3826,9 +4038,9 @@
         }
     }
 
-    auto topHandle = topHandle ();
+    auto topHandle_ = topHandle ();
     auto siblingHandle = sibling !is null ? sibling.topHandle () : null;
-    auto window = OS.GTK_WIDGET_WINDOW (topHandle);
+    auto window = OS.GTK_WIDGET_WINDOW (topHandle_);
     if (window !is null) {
         GdkWindow* siblingWindow;
         if (sibling !is null) {
@@ -3877,9 +4089,9 @@
     }
     if (fixChildren) {
         if (above) {
-            parent.moveAbove (topHandle, siblingHandle);
+            parent.moveAbove (topHandle_, siblingHandle);
         } else {
-            parent.moveBelow (topHandle, siblingHandle);
+            parent.moveBelow (topHandle_, siblingHandle);
         }
     }
     /*  Make sure that the parent internal windows are on the bottom of the stack   */
@@ -3922,10 +4134,10 @@
 void setWidgetBackground  () {
     if (fixedHandle !is null) {
         auto style = OS.gtk_widget_get_modifier_style (fixedHandle);
-        OS.gtk_widget_modify_style (fixedHandle, style);
+        modifyStyle (fixedHandle, style);
     }
     auto style = OS.gtk_widget_get_modifier_style (handle);
-    OS.gtk_widget_modify_style (handle, style);
+    modifyStyle (handle, style);
 }
 
 bool showMenu (int x, int y) {
@@ -3950,11 +4162,11 @@
 void showWidget () {
     // Comment this line to disable zero-sized widgets
     state |= ZERO_WIDTH | ZERO_HEIGHT;
-    auto topHandle = topHandle ();
+    auto topHandle_ = topHandle ();
     auto parentHandle = parent.parentingHandle ();
-    parent.setParentWindow (topHandle);
-    OS.gtk_container_add (cast(GtkContainer*)parentHandle, topHandle);
-    if (handle !is null && handle !is topHandle) OS.gtk_widget_show (handle);
+    parent.setParentWindow (topHandle_);
+    OS.gtk_container_add (cast(GtkContainer*)parentHandle, topHandle_);
+    if (handle !is null && handle !is topHandle_) OS.gtk_widget_show (handle);
     if ((state & (ZERO_WIDTH | ZERO_HEIGHT)) is 0) {
         if (fixedHandle !is null) OS.gtk_widget_show (fixedHandle);
     }
@@ -4057,6 +4269,9 @@
         case OS.GDK_Down:
         case OS.GDK_Right: {
             bool next = key is OS.GDK_Down || key is OS.GDK_Right;
+            if (parent !is null && (parent.style & DWT.MIRRORED) !is 0) {
+                if (key is OS.GDK_Left || key is OS.GDK_Right) next = !next;
+            }
             detail = next ? DWT.TRAVERSE_ARROW_NEXT : DWT.TRAVERSE_ARROW_PREVIOUS;
             break;
         }