* Reorganize the whole ReactOS codebase into a new layout. Discussing it will only...
[reactos.git] / reactos / win32ss / user / ntuser / vis.c
diff --git a/reactos/win32ss/user/ntuser/vis.c b/reactos/win32ss/user/ntuser/vis.c
new file mode 100644 (file)
index 0000000..1f0b7dc
--- /dev/null
@@ -0,0 +1,159 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS kernel
+ * PURPOSE:          Visibility computations
+ * FILE:             subsys/win32k/ntuser/vis.c
+ * PROGRAMMER:       Ge van Geldorp (ge@gse.nl)
+ */
+
+#include <win32k.h>
+DBG_DEFAULT_CHANNEL(UserWinpos);
+
+HRGN FASTCALL
+VIS_ComputeVisibleRegion(
+   PWND Wnd,
+   BOOLEAN ClientArea,
+   BOOLEAN ClipChildren,
+   BOOLEAN ClipSiblings)
+{
+   HRGN VisRgn, ClipRgn;
+   PWND PreviousWindow, CurrentWindow, CurrentSibling;
+
+   if (!Wnd || !(Wnd->style & WS_VISIBLE))
+   {
+      return NULL;
+   }
+
+   VisRgn = NULL;
+
+   if (ClientArea)
+   {
+      VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcClient);
+   }
+   else
+   {
+      VisRgn = IntSysCreateRectRgnIndirect(&Wnd->rcWindow);
+   }
+
+   /*
+    * Walk through all parent windows and for each clip the visble region
+    * to the parent's client area and exclude all siblings that are over
+    * our window.
+    */
+
+   PreviousWindow = Wnd;
+   CurrentWindow = Wnd->spwndParent;
+   while (CurrentWindow)
+   {
+      if ( CurrentWindow->state2 & WNDS2_INDESTROY ||
+           CurrentWindow->state & WNDS_DESTROYED )
+      {
+         ERR("ATM the Current Window or Parent is dead!\n");
+         if (VisRgn) GreDeleteObject(VisRgn);
+         return NULL;
+      }
+
+      if (!(CurrentWindow->style & WS_VISIBLE))
+      {
+         if (VisRgn) GreDeleteObject(VisRgn);
+         return NULL;
+      }
+
+      ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcClient);
+      NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_AND);
+      GreDeleteObject(ClipRgn);
+
+      if ((PreviousWindow->style & WS_CLIPSIBLINGS) ||
+          (PreviousWindow == Wnd && ClipSiblings))
+      {
+         CurrentSibling = CurrentWindow->spwndChild;
+         while ( CurrentSibling != NULL &&
+                 CurrentSibling != PreviousWindow )
+         {
+            if ((CurrentSibling->style & WS_VISIBLE) &&
+                !(CurrentSibling->ExStyle & WS_EX_TRANSPARENT))
+            {
+               ClipRgn = IntSysCreateRectRgnIndirect(&CurrentSibling->rcWindow);
+               /* Combine it with the window region if available */
+               if (CurrentSibling->hrgnClip && !(CurrentSibling->style & WS_MINIMIZE))
+               {
+                  NtGdiOffsetRgn(ClipRgn, -CurrentSibling->rcWindow.left, -CurrentSibling->rcWindow.top);
+                  NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentSibling->hrgnClip, RGN_AND);
+                  NtGdiOffsetRgn(ClipRgn, CurrentSibling->rcWindow.left, CurrentSibling->rcWindow.top);
+               }
+               NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
+               GreDeleteObject(ClipRgn);
+            }
+            CurrentSibling = CurrentSibling->spwndNext;
+         }
+      }
+
+      PreviousWindow = CurrentWindow;
+      CurrentWindow = CurrentWindow->spwndParent;
+   }
+
+   if (ClipChildren)
+   {
+      CurrentWindow = Wnd->spwndChild;
+      while (CurrentWindow)
+      {
+         if ((CurrentWindow->style & WS_VISIBLE) &&
+             !(CurrentWindow->ExStyle & WS_EX_TRANSPARENT))
+         {
+            ClipRgn = IntSysCreateRectRgnIndirect(&CurrentWindow->rcWindow);
+            /* Combine it with the window region if available */
+            if (CurrentWindow->hrgnClip && !(CurrentWindow->style & WS_MINIMIZE))
+            {
+               NtGdiOffsetRgn(ClipRgn, -CurrentWindow->rcWindow.left, -CurrentWindow->rcWindow.top);
+               NtGdiCombineRgn(ClipRgn, ClipRgn, CurrentWindow->hrgnClip, RGN_AND);
+               NtGdiOffsetRgn(ClipRgn, CurrentWindow->rcWindow.left, CurrentWindow->rcWindow.top);
+            }
+            NtGdiCombineRgn(VisRgn, VisRgn, ClipRgn, RGN_DIFF);
+            GreDeleteObject(ClipRgn);
+         }
+         CurrentWindow = CurrentWindow->spwndNext;
+      }
+   }
+
+   if (Wnd->hrgnClip && !(Wnd->style & WS_MINIMIZE))
+   {
+      NtGdiOffsetRgn(VisRgn, -Wnd->rcWindow.left, -Wnd->rcWindow.top);
+      NtGdiCombineRgn(VisRgn, VisRgn, Wnd->hrgnClip, RGN_AND);
+      NtGdiOffsetRgn(VisRgn, Wnd->rcWindow.left, Wnd->rcWindow.top);
+   }
+
+   return VisRgn;
+}
+
+VOID FASTCALL
+co_VIS_WindowLayoutChanged(
+   PWND Wnd,
+   HRGN NewlyExposed)
+{
+   HRGN Temp;
+   PWND Parent;
+   USER_REFERENCE_ENTRY Ref;
+
+   ASSERT_REFS_CO(Wnd);
+
+   Parent = Wnd->spwndParent;
+   if(Parent)
+   {
+      Temp = IntSysCreateRectRgn(0, 0, 0, 0);
+
+      NtGdiCombineRgn(Temp, NewlyExposed, NULL, RGN_COPY);
+      NtGdiOffsetRgn(Temp,
+                     Wnd->rcWindow.left - Parent->rcClient.left,
+                     Wnd->rcWindow.top - Parent->rcClient.top);
+
+      UserRefObjectCo(Parent, &Ref);
+      co_UserRedrawWindow(Parent, NULL, Temp,
+                          RDW_FRAME | RDW_ERASE | RDW_INVALIDATE |
+                          RDW_ALLCHILDREN);
+      UserDerefObjectCo(Parent);
+
+      GreDeleteObject(Temp);
+   }
+}
+
+/* EOF */