[Win32SS]
authorJames Tabor <james.tabor@reactos.org>
Fri, 11 Sep 2015 02:34:11 +0000 (02:34 +0000)
committerJames Tabor <james.tabor@reactos.org>
Fri, 11 Sep 2015 02:34:11 +0000 (02:34 +0000)
- Hackplement Layered Window Support from wine.
- See CORE-1576 for more information. Three days work, ReactOS needs more support for playing with GDI bits.

svn path=/trunk/; revision=69179

reactos/win32ss/CMakeLists.txt
reactos/win32ss/user/ntuser/layered.c [new file with mode: 0644]
reactos/win32ss/user/ntuser/msgqueue.c
reactos/win32ss/user/ntuser/ntstubs.c
reactos/win32ss/user/ntuser/userfuncs.h
reactos/win32ss/user/ntuser/window.c
reactos/win32ss/user/user32/windows/window.c

index ca75c75..b4b9cfa 100644 (file)
@@ -122,6 +122,7 @@ list(APPEND SOURCE
     user/ntuser/ime.c
     user/ntuser/keyboard.c
     user/ntuser/kbdlayout.c
+    user/ntuser/layered.c
     user/ntuser/menu.c
     user/ntuser/message.c
     user/ntuser/metric.c
diff --git a/reactos/win32ss/user/ntuser/layered.c b/reactos/win32ss/user/ntuser/layered.c
new file mode 100644 (file)
index 0000000..558aff1
--- /dev/null
@@ -0,0 +1,391 @@
+/*
+ * COPYRIGHT:        See COPYING in the top level directory
+ * PROJECT:          ReactOS Win32k subsystem
+ * PURPOSE:          Layered window support
+ * FILE:             win32ss/user/ntuser/layered.c
+ * PROGRAMER:
+ */
+
+#include <win32k.h>
+DBG_DEFAULT_CHANNEL(UserMisc);
+
+
+typedef struct _LRD_PROP
+{ 
+   COLORREF Key;
+   BYTE     Alpha;
+   BYTE     is_Layered;
+   BYTE     NoUsed[2];
+   DWORD    Flags;
+} LRD_PROP, *PLRD_PROP;
+
+BOOL FASTCALL
+GetLayeredStatus(PWND pWnd)
+{
+   PLRD_PROP pLrdProp = UserGetProp(pWnd, AtomLayer);
+   if (pLrdProp)
+   {
+      return pLrdProp->is_Layered;
+   }
+   return FALSE;
+}
+
+BOOL FASTCALL
+SetLayeredStatus(PWND pWnd, BYTE set)
+{
+   PLRD_PROP pLrdProp = UserGetProp(pWnd, AtomLayer);
+   if (pLrdProp)
+   {
+      pLrdProp->is_Layered = set;
+      return TRUE;
+   }
+   return FALSE;
+}
+
+BOOL FASTCALL
+IntSetLayeredWindowAttributes(PWND pWnd,
+                              COLORREF crKey,
+                              BYTE bAlpha,
+                              DWORD dwFlags)
+{
+   PLRD_PROP pLrdProp;
+   INT was_Layered;
+
+   if (!(pWnd->ExStyle & WS_EX_LAYERED) )
+   {
+      ERR("Not a Layered Window!\n");
+      return FALSE;
+   }
+
+   pLrdProp = UserGetProp(pWnd, AtomLayer);
+
+   if (!pLrdProp)
+   {
+      pLrdProp = ExAllocatePoolWithTag(PagedPool, sizeof(LRD_PROP), USERTAG_REDIRECT);
+      if (pLrdProp == NULL)
+      {
+         ERR("failed to allocate LRD_PROP\n");
+         return FALSE;
+      }
+      RtlZeroMemory(pLrdProp, sizeof(LRD_PROP));
+      IntSetProp(pWnd, AtomLayer, (HANDLE)pLrdProp);
+   }
+
+   if (pLrdProp)
+   {
+      was_Layered = pLrdProp->is_Layered;
+
+      pLrdProp->Key = crKey;
+
+      if (dwFlags & LWA_ALPHA)
+      {
+         pLrdProp->Alpha = bAlpha;
+      }
+      else
+      {
+         if (!pLrdProp->is_Layered) pLrdProp->Alpha = 0;
+      }
+
+      pLrdProp->Flags = dwFlags;
+
+      pLrdProp->is_Layered = 1;
+  
+      if (!was_Layered)
+         co_UserRedrawWindow(pWnd, NULL, NULL, RDW_INVALIDATE | RDW_ERASE | RDW_FRAME );
+   }
+   // FIXME: Now set some bits to the Window DC!!!!
+   return TRUE;
+}
+
+BOOL FASTCALL
+IntUpdateLayeredWindowI( PWND pWnd,
+                         UPDATELAYEREDWINDOWINFO *info )
+{
+   PWND Parent;
+   RECT Window, Client;
+   SIZE Offset;
+   BOOL ret = FALSE;
+   DWORD flags = SWP_NOSIZE | SWP_NOMOVE | SWP_NOZORDER | SWP_NOACTIVATE | SWP_NOREDRAW;
+
+   Window = pWnd->rcWindow;
+   Client = pWnd->rcClient;
+
+   Parent = pWnd->spwndParent;
+   if (pWnd->style & WS_CHILD && Parent)
+   {
+      RECTL_vOffsetRect(&Window, - Parent->rcClient.left, - Parent->rcClient.top);
+      RECTL_vOffsetRect(&Client, - Parent->rcClient.left, - Parent->rcClient.top);
+   }
+
+   if (info->pptDst)
+   {
+      Offset.cx = info->pptDst->x - Window.left;
+      Offset.cy = info->pptDst->y - Window.top;
+      RECTL_vOffsetRect( &Client, Offset.cx, Offset.cy );
+      RECTL_vOffsetRect( &Window, Offset.cx, Offset.cy );
+      flags &= ~SWP_NOMOVE;
+   }
+   if (info->psize)
+   {
+      Offset.cx = info->psize->cx - (Window.right  - Window.left);
+      Offset.cy = info->psize->cy - (Window.bottom - Window.top);
+      if (info->psize->cx <= 0 || info->psize->cy <= 0)
+      {
+          ERR("Update Layered Invalid Parameters\n");
+          EngSetLastError( ERROR_INVALID_PARAMETER );
+          return FALSE;
+      }
+      if ((info->dwFlags & ULW_EX_NORESIZE) && (Offset.cx || Offset.cy))
+      {
+          ERR("Wrong Size\n");
+          EngSetLastError( ERROR_INCORRECT_SIZE );
+          return FALSE;
+      }
+      Client.right  += Offset.cx;
+      Client.bottom += Offset.cy;
+      Window.right  += Offset.cx;
+      Window.bottom += Offset.cy;
+      flags &= ~SWP_NOSIZE;
+   }
+
+   if (info->hdcSrc)
+   {
+      HBRUSH hBr;
+      HDC hdc;
+      RECT Rect;
+      BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
+      COLORREF color_key = (info->dwFlags & ULW_COLORKEY) ? info->crKey : CLR_INVALID;
+
+      Rect = Window;
+
+      RECTL_vOffsetRect( &Rect, -Window.left, -Window.top );
+
+      TRACE("H %d W %d\n",Rect.bottom - Rect.top,Rect.right - Rect.left);
+
+      if (!info->hdcDst) hdc = UserGetDCEx(pWnd, NULL, DCX_USESTYLE);
+      else hdc = info->hdcDst;
+
+      hBr = NtGdiCreateSolidBrush(color_key, NULL);
+      if (hBr)
+      {
+         TRACE("Fill Color Key %x\n",color_key);
+         FillRect(hdc, &Rect, hBr);
+      }
+
+      if (info->prcDirty)
+      {
+         ERR("prcDirty\n");
+         RECTL_bIntersectRect( &Rect, &Rect, info->prcDirty );
+         NtGdiPatBlt( hdc, Rect.left, Rect.top, Rect.right - Rect.left, Rect.bottom - Rect.top, BLACKNESS );
+      }
+
+      if (info->dwFlags & ULW_ALPHA)
+      {
+         blend = *info->pblend;
+         TRACE("ULW_ALPHA bop %d scA %d aF %d\n", blend.BlendOp, blend.SourceConstantAlpha, blend.AlphaFormat);
+      }
+
+      ret = NtGdiAlphaBlend( hdc,
+                             Rect.left,
+                             Rect.top,
+                             Rect.right - Rect.left,
+                             Rect.bottom - Rect.top,
+                             info->hdcSrc,
+                             Rect.left + (info->pptSrc ? info->pptSrc->x : 0),
+                             Rect.top + (info->pptSrc ? info->pptSrc->y : 0),
+                             Rect.right - Rect.left, Rect.bottom - Rect.top,
+                             blend,
+                             0);
+
+      if (hBr) GreDeleteObject(hBr);
+      if (!info->hdcDst) UserReleaseDC(pWnd, hdc, FALSE);
+   }
+   else
+      ret = TRUE;
+
+   co_WinPosSetWindowPos(pWnd, 0, Window.left, Window.top, Window.right - Window.left, Window.bottom - Window.top, flags);
+   return ret;
+}
+
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserGetLayeredWindowAttributes(
+    HWND hwnd,
+    COLORREF *pcrKey,
+    BYTE *pbAlpha,
+    DWORD *pdwFlags)
+{
+   PLRD_PROP pLrdProp;
+   PWND pWnd;
+   BOOL Ret = FALSE;
+
+   TRACE("Enter NtUserGetLayeredWindowAttributes\n");
+
+   if (!(pWnd = UserGetWindowObject(hwnd)) ||
+       !(pWnd->ExStyle & WS_EX_LAYERED) )
+   {
+      return FALSE;
+   }
+
+   UserEnterExclusive();
+
+   pLrdProp = UserGetProp(pWnd, AtomLayer);
+
+   if (!pLrdProp)
+   {
+      TRACE("No Prop!\n");
+      goto Exit;
+   }
+
+   if (pLrdProp->is_Layered == 0)
+   {
+      goto Exit;
+   }
+
+   _SEH2_TRY
+   {
+      if (pcrKey)     *pcrKey = pLrdProp->Key;
+      if (pbAlpha)   *pbAlpha = pLrdProp->Alpha;
+      if (pdwFlags) *pdwFlags = pLrdProp->Flags;
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      SetLastNtError(_SEH2_GetExceptionCode());
+      _SEH2_YIELD(goto Exit);
+   }
+   _SEH2_END;
+
+   Ret = TRUE;
+
+Exit:
+   TRACE("Leave NtUserGetLayeredWindowAttributes, ret=%i\n", Ret);
+   UserLeave();
+   return Ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL APIENTRY
+NtUserSetLayeredWindowAttributes(HWND hwnd,
+                          COLORREF crKey,
+                          BYTE bAlpha,
+                          DWORD dwFlags)
+{
+   PWND pWnd;
+   BOOL Ret = FALSE;
+
+   TRACE("Enter NtUserSetLayeredWindowAttributes\n");
+   UserEnterExclusive();
+
+   if (!(pWnd = UserGetWindowObject(hwnd)) ||
+       !(pWnd->ExStyle & WS_EX_LAYERED) )
+   {
+      ERR("Not a Layered Window!\n");
+      goto Exit;
+   }
+
+   Ret = IntSetLayeredWindowAttributes(pWnd, crKey, bAlpha, dwFlags);
+Exit:
+   TRACE("Leave NtUserSetLayeredWindowAttributes, ret=%i\n", Ret);
+   UserLeave();
+   return Ret;
+}
+
+/*
+ * @implemented
+ */
+BOOL
+APIENTRY
+NtUserUpdateLayeredWindow(
+   HWND hwnd,
+   HDC hdcDst,
+   POINT *pptDst,
+   SIZE *psize,
+   HDC hdcSrc,
+   POINT *pptSrc,
+   COLORREF crKey,
+   BLENDFUNCTION *pblend,
+   DWORD dwFlags,
+   RECT *prcDirty)
+{
+   UPDATELAYEREDWINDOWINFO info;
+   POINT Dst, Src; 
+   SIZE Size;
+   RECT Dirty;
+   BLENDFUNCTION blend = { AC_SRC_OVER, 0, 255, 0 };
+   PWND pWnd;
+   BOOL Ret = FALSE;
+
+   TRACE("Enter NtUserUpdateLayeredWindow\n");
+
+   if (!(pWnd = UserGetWindowObject(hwnd)))
+   {
+      return FALSE;
+   }
+
+   _SEH2_TRY
+   {
+      if (pptDst)
+      {
+         ProbeForRead(pptDst, sizeof(POINT), 1);
+         Dst = *pptDst;
+      }
+      if (pptSrc)
+      {
+         ProbeForRead(pptSrc, sizeof(POINT), 1);
+         Src = *pptSrc;
+      }
+      ProbeForRead(psize, sizeof(SIZE), 1);
+      Size = *psize;
+      if (pblend)
+      {
+         ProbeForRead(pblend, sizeof(BLENDFUNCTION), 1);
+         blend = *pblend;
+      }
+      if (prcDirty)
+      {
+         ProbeForRead(prcDirty, sizeof(RECT), 1);
+         Dirty = *prcDirty;
+      }
+   }
+   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
+   {
+      EngSetLastError( ERROR_INVALID_PARAMETER );
+      _SEH2_YIELD(return FALSE);
+   }
+   _SEH2_END;
+
+   UserEnterExclusive();
+
+   if ( GetLayeredStatus(pWnd) ||
+        dwFlags & ~(ULW_COLORKEY | ULW_ALPHA | ULW_OPAQUE | ULW_EX_NORESIZE) ||
+       !(pWnd->ExStyle & WS_EX_LAYERED) )
+   {
+      ERR("Layered Window Invalid Parameters\n");
+      EngSetLastError( ERROR_INVALID_PARAMETER );
+      goto Exit;
+   }
+
+   info.cbSize   = sizeof(info);
+   info.hdcDst   = hdcDst;
+   info.pptDst   = pptDst? &Dst : 0;
+   info.psize    = &Size;
+   info.hdcSrc   = hdcSrc;
+   info.pptSrc   = pptSrc ? &Src : 0;
+   info.crKey    = crKey;
+   info.pblend   = &blend;
+   info.dwFlags  = dwFlags;
+   info.prcDirty = prcDirty ? &Dirty : 0;
+   Ret = IntUpdateLayeredWindowI( pWnd, &info );
+Exit:
+   TRACE("Leave NtUserUpdateLayeredWindow, ret=%i\n", Ret);
+   UserLeave();
+   return Ret;
+}
+
+/* EOF */
index bf12a5a..dce1f9b 100644 (file)
@@ -62,7 +62,7 @@ IntTopLevelWindowFromPoint(INT x, INT y)
         }
 
         if ((pWnd->style & WS_VISIBLE) &&
-            (pWnd->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) == 0 &&
+            (pWnd->ExStyle & (WS_EX_LAYERED|WS_EX_TRANSPARENT)) != (WS_EX_LAYERED|WS_EX_TRANSPARENT) &&
             IntPtInWindow(pWnd, x, y))
             return pWnd;
     }
index d45237d..6642c8f 100644 (file)
@@ -980,53 +980,6 @@ NtUserLockWindowUpdate(HWND hWnd)
    return 0;
 }
 
-BOOL
-APIENTRY
-NtUserGetLayeredWindowAttributes(
-    HWND hwnd,
-    COLORREF *pcrKey,
-    BYTE *pbAlpha,
-    DWORD *pdwFlags)
-{
-    STUB;
-    return 0;
-}
-
-/*
- * @unimplemented
- */
-BOOL APIENTRY
-NtUserSetLayeredWindowAttributes(HWND hwnd,
-                          COLORREF crKey,
-                          BYTE bAlpha,
-                          DWORD dwFlags)
-{
-  STUB;
-  return FALSE;
-}
-
-/*
- * @unimplemented
- */
-BOOL
-APIENTRY
-NtUserUpdateLayeredWindow(
-   HWND hwnd,
-   HDC hdcDst,
-   POINT *pptDst,
-   SIZE *psize,
-   HDC hdcSrc,
-   POINT *pptSrc,
-   COLORREF crKey,
-   BLENDFUNCTION *pblend,
-   DWORD dwFlags,
-   RECT *prcDirty)
-{
-   STUB
-
-   return 0;
-}
-
 DWORD APIENTRY
 NtUserQuerySendMessage(DWORD Unknown0)
 {
index 2addad1..34e1408 100644 (file)
@@ -145,4 +145,9 @@ HBRUSH FASTCALL DefWndControlColor(HDC hDC,UINT ctlType);
 BOOL UserDrawSysMenuButton(PWND pWnd, HDC hDC, LPRECT Rect, BOOL Down);
 BOOL UserPaintCaption(PWND pWnd, INT Flags);
 
+/************** LAYERED **************/
+
+BOOL FASTCALL SetLayeredStatus(PWND pWnd, BYTE set);
+BOOL FASTCALL GetLayeredStatus(PWND pWnd);
+
 /* EOF */
index d63ec08..d04475f 100644 (file)
@@ -3546,6 +3546,11 @@ co_IntSetWindowLong(HWND hWnd, DWORD Index, LONG NewValue, BOOL Ansi, BOOL bAlte
             else
                Style.styleNew &= ~WS_EX_WINDOWEDGE;
 
+            if (!(Window->ExStyle & WS_EX_LAYERED))
+            {
+               SetLayeredStatus(Window, 0);
+            }
+
             Window->ExStyle = (DWORD)Style.styleNew;
 
             co_IntSendMessage(hWnd, WM_STYLECHANGED, GWL_EXSTYLE, (LPARAM) &Style);
index 885c56f..3a5efa3 100644 (file)
@@ -1713,8 +1713,11 @@ UpdateLayeredWindow( HWND hwnd,
                      BLENDFUNCTION *pbl,
                      DWORD dwFlags)
 {
-  if ( dwFlags & ULW_EX_NORESIZE)
-     dwFlags = ~(ULW_EX_NORESIZE|ULW_OPAQUE|ULW_ALPHA|ULW_COLORKEY);
+  if (dwFlags & ULW_EX_NORESIZE)  /* only valid for UpdateLayeredWindowIndirect */
+  {
+     SetLastError( ERROR_INVALID_PARAMETER );
+     return FALSE;
+  }
   return NtUserUpdateLayeredWindow( hwnd,
                                     hdcDst,
                                     pptDst,