diff --git a/src/libply/ply-frame-buffer.c b/src/libply/ply-frame-buffer.c
index ee079db..e52f138 100644
--- a/src/libply/ply-frame-buffer.c
+++ b/src/libply/ply-frame-buffer.c
@@ -519,51 +519,228 @@ ply_frame_buffer_area_union (ply_frame_buffer_area_t *area1,
 
 static void
 integrate_area_with_flush_area (ply_frame_buffer_t      *buffer,
+                                ply_list_node_t         *node,
                                 ply_frame_buffer_area_t *new_area)
 {
-  ply_list_node_t *node;
-  ply_frame_buffer_area_t overlapping_area;
-
-  /* FIXME: The logic in the function isn't as sophisticated as it could be.
-   * It only culls if one old area completely overlaps the new flush area.
-   *
-   * It doesn't cull if two or more old flush areas collectively overlap the
-   * new flush area.
-   */
-
+  if (new_area->width == 0) return;
+  if (new_area->height == 0) return;
   node = ply_list_get_first_node (buffer->areas_to_flush);
   while (node != NULL)
     {
       ply_list_node_t *next_node;
-      ply_frame_buffer_area_t *existing_area_to_flush;
-
-      existing_area_to_flush = (ply_frame_buffer_area_t *) ply_list_node_get_data (node);
-
+      ply_frame_buffer_area_t *second_new_area;
+      ply_frame_buffer_area_t *old_area;
+      old_area = (ply_frame_buffer_area_t *) ply_list_node_get_data (node);
       next_node = ply_list_get_next_node (buffer->areas_to_flush, node);
-
-      ply_frame_buffer_area_intersect (new_area,
-                                       existing_area_to_flush,
-                                       &overlapping_area);
-
-      /* If an existing flush area is completely inside the
-       * new area, then we can remove the old area from the list.
-       *
-       * If the new area is completely inside an old area then
-       * we don't need to add the new area at all.
-       */
-      if (overlapping_area.width == existing_area_to_flush->width &&
-          overlapping_area.height == existing_area_to_flush->height)
+      
+      /*
+        Say we have an overlap between rectangle A and rectangle B and C denotes the overlap.
+        Depending on the type of overlap we can create a non overlapping addition to the set.
+        
+        1:Collision on one side         2:Collision on two sides  
+        Trim one of the rectanges       Break into two rectangles 
+        
+        AAAAA         AAAAA               AAAAA         AAAAA     
+        AAACCBBB      AAAAABBB            AAAAA         AAAAA     
+        AAACCBBB  =>  AAAAABBB            AAACCBBB  =>  AAAAAbbb  
+        AAACCBBB      AAAAABBB            AAACCBBB      AAAAAbbb  
+        AAAAA         AAAAA                  BBBBB         BBBBB  
+                                             BBBBB         BBBBB
+        
+        3:Collision on opposite sides   4:Fully contained
+        Break into two rectangles       Throw away the rectangle 
+
+         AAAAA        AAAAA              AAAAA        AAAAA
+        BCCCCCB      BAAAAAb             ACCCA        AAAAA
+        BCCCCCB  =>  BAAAAAb             ACCCA   =>   AAAAA
+        BCCCCCB      BAAAAAb             ACCCA        AAAAA
+         AAAAA        AAAAA              AAAAA        AAAAA
+
+        
+        
+      */
+      
+      int h_collision = 0;        /* 0=no overlap 1=left 2=right 3=left and right 4=between l and r */
+      int v_collision = 0;        /* 0=no overlap 1=top 2=bottom 3=top and bottom 4=between t and b */
+      
+      if (new_area->x >= old_area->x && (new_area->x + new_area->width) <= (old_area->x + old_area->width))
+        h_collision = 4;
+      else
+        {                                       /* Remember: x+width points to the first pixel outside the rectangle*/
+          if (new_area->x < old_area->x &&
+              (new_area->x + (int)new_area->width) > old_area->x)
+            h_collision |= 1;                     /* new_area colllided with the left edge of old_area */
+          if (new_area->x < (old_area->x + (int)old_area->width) &&
+              (new_area->x + (int)new_area->width) >= (old_area->x + (int)old_area->width))
+            h_collision |= 2;                     /* new_area colllided with the right edge of old_area */
+        }
+      
+      if (new_area->y >= old_area->y && (new_area->y + new_area->height) <= (old_area->y + old_area->height))
+        v_collision = 4;
+      else
         {
-          free (existing_area_to_flush);
-          ply_list_remove_node (buffer->areas_to_flush, node);
+          if (new_area->y < old_area->y &&
+              (new_area->y + (int)new_area->height) > old_area->y)
+            v_collision |= 1;
+          if (new_area->y < (old_area->y + (int)old_area->height) &&
+              (new_area->y + (int)new_area->height) >= (old_area->y + (int)old_area->height))
+            v_collision |= 2;
         }
-      else if (overlapping_area.width == new_area->width &&
-               overlapping_area.height == new_area->height)
+      
+      if (h_collision && v_collision)
         {
-          free (new_area);
-          return;
+          h_collision &= 3;     /* if (collision == 4 ) collision = 0*/
+          v_collision &= 3;
+          
+          switch(v_collision)
+            {
+              case 0:
+                {
+                  switch (h_collision)
+                    {
+                      case 0:   /* new fully contained within old, remove new */
+                        free (new_area);
+                        return;
+                      case 1:   /* collision with old left edge only, trim new */
+                        new_area->width = old_area->x - new_area->x;
+                        break;
+                      case 2:   /* collision with old right edge only, trim new */
+                        new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
+                        new_area->x = old_area->x + old_area->width;
+                        break;
+                      case 3:   /* collision with old left and right edges but not top and botton, split new into two */
+                        {
+                          second_new_area = malloc (sizeof (ply_frame_buffer_area_t));
+                          second_new_area->x = old_area->x + old_area->width;
+                          second_new_area->y = new_area->y;
+                          second_new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
+                          second_new_area->height = new_area->height;
+                          new_area->width = old_area->x - new_area->x;
+
+                          integrate_area_with_flush_area (buffer, node, second_new_area);
+                          integrate_area_with_flush_area (buffer, node, new_area);
+                          return;
+                        }
+                    }
+                  break;
+                }
+              case 1:
+                {
+                  switch (h_collision)
+                    {
+                      case 0:   /* collision with old top edge only, trim new */
+                        new_area->height = old_area->y - new_area->y;
+                        break;
+                      case 1:   /* collision with old top left corner, split new into two */
+                        {
+                          second_new_area = malloc (sizeof (ply_frame_buffer_area_t));
+                          second_new_area->x = new_area->x;
+                          second_new_area->y = old_area->y;
+                          second_new_area->width = old_area->x - new_area->x;
+                          second_new_area->height = (new_area->y + new_area->height) - old_area->y;
+                          new_area->height = old_area->y - new_area->y;
+
+                          integrate_area_with_flush_area (buffer, node, second_new_area);
+                          integrate_area_with_flush_area (buffer, node, new_area);
+                          return;
+                        }
+                      case 2:   /* collision with old top right corner, split new into two */
+                        {
+                          second_new_area = malloc (sizeof (ply_frame_buffer_area_t));
+                          second_new_area->x = old_area->x + old_area->width;
+                          second_new_area->y = old_area->y;
+                          second_new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
+                          second_new_area->height = (new_area->y + new_area->height) - old_area->y;
+                          new_area->height = old_area->y - new_area->y;
+
+                          integrate_area_with_flush_area (buffer, node, second_new_area);
+                          integrate_area_with_flush_area (buffer, node, new_area);
+                          return;
+                        }
+                      case 3:   /* collision with old top, left and right corners, trim old */
+                        old_area->height = (old_area->y + old_area->height) - (new_area->y + new_area->height);
+                        old_area->y = new_area->y + new_area->height;
+                        break;
+                    }
+                  break;
+                }
+              case 2:
+                {
+                  switch (h_collision)
+                    {
+                      case 0:   /* collision with old botoom edge only, trim new */
+                        new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
+                        new_area->y = old_area->y + old_area->height;
+                        break;
+                      case 1:   /* collision with old bottom left corner, split new into two */
+                        {
+                          second_new_area = malloc (sizeof (ply_frame_buffer_area_t));
+                          second_new_area->x = new_area->x;
+                          second_new_area->y = new_area->y;
+                          second_new_area->width = old_area->x - new_area->x;
+                          second_new_area->height = (old_area->y + old_area->height) - new_area->y;
+
+                          new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
+                          new_area->y = old_area->y + old_area->height;
+
+                          integrate_area_with_flush_area (buffer, node, second_new_area);
+                          integrate_area_with_flush_area (buffer, node, new_area);
+                          return;
+                        }
+                      case 2:   /* collision with old bottom right corner, split new into two */
+                        {
+                          second_new_area = malloc (sizeof (ply_frame_buffer_area_t));
+                          second_new_area->x = old_area->x + old_area->width;
+                          second_new_area->y = new_area->y;
+                          second_new_area->width = (new_area->x + new_area->width) - (old_area->x + old_area->width);
+                          second_new_area->height = (old_area->y + old_area->height) - new_area->y;
+
+                          new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
+                          new_area->y = old_area->y + old_area->height;
+
+                          integrate_area_with_flush_area (buffer, node, second_new_area);
+                          integrate_area_with_flush_area (buffer, node, new_area);
+                          return;
+                        }
+                      case 3:   /* collision with old bottom, left and right corners, trim old */
+                        old_area->height = new_area->y - old_area->y;
+                        break;
+                    }
+                  break;
+                }
+              case 3:
+                {
+                  switch (h_collision)
+                    {
+                      case 0:   /* collision with old top and bottom edges but not left and right, split new into two */
+                        {
+                          second_new_area = malloc (sizeof (ply_frame_buffer_area_t));
+                          second_new_area->x = new_area->x;
+                          second_new_area->y = old_area->y + old_area->height;
+                          second_new_area->width = new_area->width;
+                          second_new_area->height = (new_area->y + new_area->height) - (old_area->y + old_area->height);
+                          new_area->height = old_area->y - new_area->y;
+
+                          integrate_area_with_flush_area (buffer, node, second_new_area);
+                          integrate_area_with_flush_area (buffer, node, new_area);
+                          return;
+                        }
+                      case 1:   /* collision with old left, top and bottom corners, trim old */
+                        old_area->width = (old_area->x + old_area->width) - (new_area->x + new_area->width);
+                        old_area->x = new_area->x + new_area->width;
+                        break;
+                      case 2:   /* collision with old right, top and bottom corners, trim old */
+                        old_area->width = new_area->x - old_area->x;
+                        break;
+                      case 3:   /* old fully contained within new, remove old */
+                        free (old_area);
+                        ply_list_remove_node (buffer->areas_to_flush, node);
+                        break;
+                    }
+                  break;
+                }
+            }
         }
-
       node = next_node;
     }
 
@@ -588,7 +765,9 @@ ply_frame_buffer_add_area_to_flush_area (ply_frame_buffer_t      *buffer,
       return;
     }
 
-  integrate_area_with_flush_area (buffer, cropped_area);
+  integrate_area_with_flush_area (buffer, 
+                                  ply_list_get_first_node (buffer->areas_to_flush),
+                                  cropped_area);
 }
 
 static bool