Alexandre Julliard : server: Mirror the window region for RTL windows in get/ set_window_region and redraw_window.

Alexandre Julliard julliard at winehq.org
Tue Sep 28 11:13:30 CDT 2010


Module: wine
Branch: master
Commit: d56ac06260daaa82cfcf7a15d3fe10de574be6d3
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=d56ac06260daaa82cfcf7a15d3fe10de574be6d3

Author: Alexandre Julliard <julliard at winehq.org>
Date:   Mon Sep 27 20:46:41 2010 +0200

server: Mirror the window region for RTL windows in get/set_window_region and redraw_window.

---

 server/protocol.def |    6 +++---
 server/region.c     |   23 +++++++++++++++++++++++
 server/user.h       |   10 ++++++++++
 server/window.c     |   31 ++++++++++++++++++-------------
 4 files changed, 54 insertions(+), 16 deletions(-)

diff --git a/server/protocol.def b/server/protocol.def
index 687fe6c..ccc87fe 100644
--- a/server/protocol.def
+++ b/server/protocol.def
@@ -2405,7 +2405,7 @@ enum coords_relative
     user_handle_t  window;        /* handle to the window */
 @REPLY
     data_size_t    total_size;    /* total size of the resulting region */
-    VARARG(region,rectangles);    /* list of rectangles for the region */
+    VARARG(region,rectangles);    /* list of rectangles for the region (in window coords) */
 @END
 
 
@@ -2413,7 +2413,7 @@ enum coords_relative
 @REQ(set_window_region)
     user_handle_t  window;        /* handle to the window */
     int            redraw;        /* redraw the window? */
-    VARARG(region,rectangles);    /* list of rectangles for the region */
+    VARARG(region,rectangles);    /* list of rectangles for the region (in window coords) */
 @END
 
 
@@ -2449,7 +2449,7 @@ enum coords_relative
 @REQ(redraw_window)
     user_handle_t  window;        /* handle to the window */
     unsigned int   flags;         /* RDW_* flags */
-    VARARG(region,rectangles);    /* list of rectangles for the region */
+    VARARG(region,rectangles);    /* list of rectangles for the region (in window coords) */
 @END
 
 
diff --git a/server/region.c b/server/region.c
index 2efbd30..8b85c34 100644
--- a/server/region.c
+++ b/server/region.c
@@ -711,6 +711,29 @@ void offset_region( struct region *region, int x, int y )
     region->extents.bottom += y;
 }
 
+/* mirror a region relative to a window client rect */
+void mirror_region( const rectangle_t *client_rect, struct region *region )
+{
+    int start, end, i, j;
+
+    for (start = 0; start < region->num_rects; start = end + 1)
+    {
+        for (end = start; end < region->num_rects - 1; end++)
+            if (region->rects[end + 1].top != region->rects[end].top) break;
+        for (i = start, j = end; i < j; i++, j--)
+        {
+            rectangle_t rect = region->rects[j];
+            region->rects[i] = region->rects[j];
+            region->rects[j] = rect;
+            mirror_rect( client_rect, &region->rects[j] );
+            mirror_rect( client_rect, &region->rects[i] );
+        }
+        if (i == j) mirror_rect( client_rect, &region->rects[i] );
+    }
+    mirror_rect( client_rect, &region->extents );
+}
+
+
 /* make a copy of a region; returns dst or NULL on error */
 struct region *copy_region( struct region *dst, const struct region *src )
 {
diff --git a/server/user.h b/server/user.h
index 1f0d909..6ac0398 100644
--- a/server/user.h
+++ b/server/user.h
@@ -114,6 +114,7 @@ extern rectangle_t *get_region_data_and_free( struct region *region, data_size_t
 extern int is_region_empty( const struct region *region );
 extern void get_region_extents( const struct region *region, rectangle_t *rect );
 extern void offset_region( struct region *region, int x, int y );
+extern void mirror_region( const rectangle_t *client_rect, struct region *region );
 extern struct region *copy_region( struct region *dst, const struct region *src );
 extern struct region *intersect_region( struct region *dst, const struct region *src1,
                                         const struct region *src2 );
@@ -164,4 +165,13 @@ extern void set_process_default_desktop( struct process *process, struct desktop
 extern void close_process_desktop( struct process *process );
 extern void close_thread_desktop( struct thread *thread );
 
+/* mirror a rectangle respective to the window client area */
+static inline void mirror_rect( const rectangle_t *client_rect, rectangle_t *rect )
+{
+    int width = client_rect->right - client_rect->left;
+    int tmp = rect->left;
+    rect->left = width - rect->right;
+    rect->right = width - tmp;
+}
+
 #endif  /* __WINE_SERVER_USER_H */
diff --git a/server/window.c b/server/window.c
index bb66a39..e3dc47a 100644
--- a/server/window.c
+++ b/server/window.c
@@ -905,16 +905,6 @@ static inline void offset_rect( rectangle_t *rect, int offset_x, int offset_y )
 }
 
 
-/* mirror a rectangle respective to the window client area */
-static inline void mirror_rect( const rectangle_t *window_rect, rectangle_t *rect )
-{
-    int width = window_rect->right - window_rect->left;
-    int tmp = rect->left;
-    rect->left = width - rect->right;
-    rect->right = width - tmp;
-}
-
-
 /* set the region to the client rect clipped by the window rect, in parent-relative coordinates */
 static void set_region_client_rect( struct region *region, struct window *win )
 {
@@ -2314,15 +2304,28 @@ DECL_HANDLER(get_visible_region)
 /* get the window region */
 DECL_HANDLER(get_window_region)
 {
+    rectangle_t *data;
     struct window *win = get_window( req->window );
 
     if (!win) return;
+    if (!win->win_region) return;
 
-    if (win->win_region)
+    if (win->ex_style & WS_EX_LAYOUTRTL)
     {
-        rectangle_t *data = get_region_data( win->win_region, get_reply_max_size(), &reply->total_size );
-        if (data) set_reply_data_ptr( data, reply->total_size );
+        struct region *region = create_empty_region();
+
+        if (!region) return;
+        if (!copy_region( region, win->win_region ))
+        {
+            free_region( region );
+            return;
+        }
+        mirror_region( &win->window_rect, region );
+        data = get_region_data_and_free( region, get_reply_max_size(), &reply->total_size );
     }
+    else data = get_region_data( win->win_region, get_reply_max_size(), &reply->total_size );
+
+    if (data) set_reply_data_ptr( data, reply->total_size );
 }
 
 
@@ -2338,6 +2341,7 @@ DECL_HANDLER(set_window_region)
     {
         if (!(region = create_region_from_req_data( get_req_data(), get_req_data_size() )))
             return;
+        if (win->ex_style & WS_EX_LAYOUTRTL) mirror_region( &win->window_rect, region );
     }
     set_window_region( win, region, req->redraw );
 }
@@ -2458,6 +2462,7 @@ DECL_HANDLER(redraw_window)
         {
             if (!(region = create_region_from_req_data( get_req_data(), get_req_data_size() )))
                 return;
+            if (win->ex_style & WS_EX_LAYOUTRTL) mirror_region( &win->client_rect, region );
         }
     }
 




More information about the wine-cvs mailing list