Author: fireball
Date: Sat Nov 21 16:02:55 2009
New Revision: 44255
URL: http://svn.reactos.org/svn/reactos?rev=44255&view=rev
Log:
- winent.drv: Inform SWM in all cases when a window really changes its size or position.
- SWM: Recalculate clipping of all windows every time a window state is changed. This is more time consuming rather than the incremental approach used earlier, however it's 100% fail proof.
- The above changes provide a substantial improvement to the window clipping and drawing in arwinss, except for a few unhandled cases.
Modified:
branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c
branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c
Modified: branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c
URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/dll/win32/winen…
==============================================================================
--- branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] (original)
+++ branches/arwinss/reactos/dll/win32/winent.drv/userdrv.c [iso-8859-1] Sat Nov 21 16:02:55 2009
@@ -535,6 +535,9 @@
if (flags & DCX_CLIPCHILDREN) escape.clip_children = TRUE;
}
+
+ //FIXME("hdc %x, hwnd %x, top %x\n win_rect %s, top_rect %s\n", hdc, hwnd, top,
+ // wine_dbgstr_rect(win_rect), wine_dbgstr_rect(top_rect));
escape.dc_rect.left = win_rect->left - top_rect->left;
escape.dc_rect.top = win_rect->top - top_rect->top;
@@ -838,7 +841,7 @@
LRESULT CDECL RosDrv_SysCommand( HWND hwnd, WPARAM wparam, LPARAM lparam )
{
- UNIMPLEMENTED;
+ //UNIMPLEMENTED;
return -1;
}
@@ -864,8 +867,8 @@
SwmPosChanging(hwnd, window_rect);
- TRACE( "win %x pos is changing. vis rect %s, win rect %s\n",
- hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(window_rect) );
+ //TRACE( "win %x pos is changing. vis rect %s, win rect %s\n",
+ // hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(window_rect) );
*visible_rect = *window_rect;
}
@@ -882,8 +885,8 @@
if (!data) return;
- TRACE( "win %x pos changed. new vis rect %s, old whole rect %s, swp_flags %x insert_after %x\n",
- hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect), swp_flags, insert_after );
+ //TRACE( "win %x pos changed. new vis rect %s, old whole rect %s, swp_flags %x insert_after %x\n",
+ // hwnd, wine_dbgstr_rect(visible_rect), wine_dbgstr_rect(&data->whole_rect), swp_flags, insert_after );
old_whole_rect = data->whole_rect;
old_client_rect = data->client_rect;
@@ -911,12 +914,13 @@
;//move_window_bits( data, &old_whole_rect, &data->whole_rect, &old_client_rect );
else
SwmPosChanged(hwnd, &data->whole_rect, &old_whole_rect);
- FIXME("change1\n");
+ //FIXME("change1\n");
}
else
{
//move_window_bits( data, &valid_rects[1], &valid_rects[0], &old_client_rect );
- FIXME("change2\n");
+ //FIXME("change2\n");
+ SwmPosChanged(hwnd, &data->whole_rect, &old_whole_rect);
}
}
@@ -925,10 +929,10 @@
/* Pass show/hide information to the window manager */
if (swp_flags & SWP_SHOWWINDOW)
{
- if (swp_flags & SWP_NOZORDER) FIXME("no zorder change, ignoring!\n");
- if (swp_flags & SWP_NOACTIVATE) FIXME("no activate change, ignoring!\n");
-
- SwmSetForeground(hwnd);
+ if (swp_flags & SWP_NOZORDER) FIXME("no zorder change for hwnd %x, ignoring!\n", hwnd);
+ //if (swp_flags & SWP_NOACTIVATE) FIXME("no activate change, ignoring!\n");
+
+ //SwmSetForeground(hwnd);
SwmShowWindow(hwnd, TRUE);
}
else if (swp_flags & SWP_HIDEWINDOW)
Modified: branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c
URL: http://svn.reactos.org/svn/reactos/branches/arwinss/reactos/subsystems/win3…
==============================================================================
--- branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c [iso-8859-1] (original)
+++ branches/arwinss/reactos/subsystems/win32/win32k/swm/winman.c [iso-8859-1] Sat Nov 21 16:02:55 2009
@@ -21,6 +21,10 @@
void redraw_window( struct window *win, struct region *region, int frame, unsigned int flags );
void req_update_window_zorder( const struct update_window_zorder_request *req, struct update_window_zorder_reply *reply );
+PSWM_WINDOW NTAPI SwmGetTopWindow();
+VOID NTAPI SwmClipAllWindows();
+VOID NTAPI SwmDrawAllWindows();
+
VOID NTAPI SwmDumpRegion(struct region *Region);
VOID NTAPI SwmDumpWindows();
VOID NTAPI SwmDebugDrawWindows();
@@ -55,7 +59,6 @@
NTAPI
SwmInvalidateRegion(PSWM_WINDOW Window, struct region *Region, rectangle_t *Rect)
{
-#if 1
struct window *Win;
struct update_window_zorder_request req;
struct update_window_zorder_reply reply;
@@ -68,8 +71,8 @@
/* Calculate what areas to paint */
UserEnterExclusive();
- DPRINT1("SwmInvalidateRegion hwnd %x, region:\n", Window->hwnd);
- SwmDumpRegion(Region);
+ DPRINT("SwmInvalidateRegion hwnd %x, region:\n", Window->hwnd);
+ //SwmDumpRegion(Region);
Win = get_window((UINT_PTR)Window->hwnd);
if (!Win)
{
@@ -82,10 +85,12 @@
/* Bring every rect in a region to front */
for (i=0; i<Region->num_rects; i++)
{
+#if 0
DbgPrint("(%d,%d)-(%d,%d), and redraw coords (%d,%d)-(%d,%d); ", Region->rects[i].left, Region->rects[i].top,
Region->rects[i].right, Region->rects[i].bottom,
Region->rects[i].left - Window->Window.left, Region->rects[i].top - Window->Window.top,
Region->rects[i].right - Window->Window.left, Region->rects[i].bottom - Window->Window.top);
+#endif
req.rect = Region->rects[i];
req.window = (UINT_PTR)Window->hwnd;
@@ -102,23 +107,24 @@
UserLeave();
free_region(ClientRegion);
-#endif
-}
-
-VOID
-NTAPI
-SwmMarkInvisible(struct region *Region)
+}
+
+VOID
+NTAPI
+SwmPaintRegion(struct region *Region)
{
PLIST_ENTRY Current;
PSWM_WINDOW Window;
- struct region *WindowRegion;
- struct region *InvisibleRegion;
-
- /* Make a copy of the invisible region */
- InvisibleRegion = create_empty_region();
- copy_region(InvisibleRegion, Region);
-
- /* Traverse the list to find our window */
+ struct region *RegionToPaint;
+ struct region *Intersection;
+
+ /* Make a copy of the region */
+ RegionToPaint = create_empty_region();
+ copy_region(RegionToPaint, Region);
+
+ Intersection = create_empty_region();
+
+ /* Traverse the list of windows and paint if something intersects */
Current = SwmWindows.Flink;
while(Current != &SwmWindows)
{
@@ -132,55 +138,141 @@
continue;
}
- /* Get window's region */
- WindowRegion = create_empty_region();
- set_region_rect(WindowRegion, &Window->Window);
-
- //DPRINT1("Window region ext:\n");
- //SwmDumpRegion(WindowRegion);
- //DPRINT1("Region to mark invisible ext:\n");
- //SwmDumpRegion(Region);
-
- /* Region to mark invisible for this window = Update region X Window region */
- intersect_region(WindowRegion, WindowRegion, InvisibleRegion);
-
- /* Check if it's empty */
- if (!is_region_empty(WindowRegion))
+ /* Check if this window has something in common with the */
+ intersect_region(Intersection, RegionToPaint, Window->Visible);
+ if (!is_region_empty(Intersection))
{
- //DPRINT1("Subtracting region\n");
- //SwmDumpRegion(WindowRegion);
- //DPRINT1("From visible region\n");
- //SwmDumpRegion(Window->Visible);
-
- /* If it's not empty, subtract it from visible region */
- subtract_region(Window->Visible, Window->Visible, WindowRegion);
-
- /* And subtract that part from our invisible region */
- subtract_region(InvisibleRegion, InvisibleRegion, WindowRegion);
+ /* We have a region to paint, subtract it from total update region */
+ subtract_region(RegionToPaint, RegionToPaint, Intersection);
+
+ /* Paint it */
+ SwmInvalidateRegion(Window, Intersection, NULL);
}
- free_region(WindowRegion);
-
- /* Break if our whole invisible region is mapped to underlying windows */
- if (is_region_empty(InvisibleRegion)) break;
+ /* If we exhausted the painting region - break out of this loop */
+ if (is_region_empty(RegionToPaint)) break;
/* Advance to the next window */
Current = Current->Flink;
}
- free_region(InvisibleRegion);
-}
-
-/* NOTE: It alters the passed region! */
-VOID
-NTAPI
-SwmMarkVisible(struct region *Region)
+ /* Free allocated regions */
+ free_region(RegionToPaint);
+ free_region(Intersection);
+}
+
+VOID
+NTAPI
+SwmRecalculateVisibility(PSWM_WINDOW CalcWindow)
{
PLIST_ENTRY Current;
PSWM_WINDOW Window;
- struct region *WindowRegion;
-
- /* Go through every window from nearest to farthest */
+ struct region *TempRegion;
+ struct region *NewRegion, *DiffRegion, *ParentRegion;
+
+ DPRINT("Calculating visibility for %x\n", CalcWindow->hwnd);
+
+ /* Check if this window is already on top */
+ if (CalcWindow == SwmGetTopWindow())
+ {
+ /* It is, make sure it's fully visible */
+ NewRegion = create_empty_region();
+ set_region_rect(NewRegion, &CalcWindow->Window);
+
+ /* Compute the difference into the temp region */
+ DiffRegion = create_empty_region();
+ subtract_region(DiffRegion, NewRegion, CalcWindow->Visible);
+
+ /* Now get rid of the old visible region */
+ free_region(CalcWindow->Visible);
+ CalcWindow->Visible = NewRegion;
+
+ /* Show the difference, if any */
+ //if (!is_region_empty(DiffRegion))
+ // SwmInvalidateRegion(CalcWindow, DiffRegion, NULL);
+
+ /* Free up temporary regions */
+ free_region(DiffRegion);
+
+ return;
+ }
+
+ ParentRegion = create_empty_region();
+
+ /* Create a whole window region */
+ NewRegion = create_empty_region();
+ set_region_rect(NewRegion, &CalcWindow->Window);
+
+ /* Compile a total region clipped by parent windows */
+ Current = CalcWindow->Entry.Blink;
+ while(Current != &SwmWindows)
+ {
+ Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry);
+
+ /* Skip hidden windows */
+ if (Window->Hidden)
+ {
+ /* Advance to the next window */
+ Current = Current->Blink;
+ continue;
+ }
+ DPRINT("hwnd: %x\n", Window->hwnd);
+
+ /* Calculate window's region */
+ TempRegion = create_empty_region();
+ set_region_rect(TempRegion, &Window->Window);
+
+ /* Intersect it with the target window's region */
+ intersect_region(TempRegion, TempRegion, NewRegion);
+
+ /* Union it with parent if it's not empty and free temp region */
+ if (!is_region_empty(TempRegion))
+ union_region(ParentRegion, ParentRegion, TempRegion);
+ free_region(TempRegion);
+
+ /* Advance to the previous window */
+ Current = Current->Blink;
+ }
+
+ DPRINT("Parent region:\n");
+ //SwmDumpRegion(ParentRegion);
+
+ /* Remove parts clipped by parents from the window region */
+ if (!is_region_empty(ParentRegion))
+ subtract_region(NewRegion, NewRegion, ParentRegion);
+
+ DPRINT("New visible region:\n");
+ //SwmDumpRegion(NewRegion);
+
+ /* Compute the difference between old and new visible
+ regions into the temp region */
+ DiffRegion = create_empty_region();
+ subtract_region(DiffRegion, CalcWindow->Visible, NewRegion);
+
+ DPRINT("Diff between old and new:\n");
+ //SwmDumpRegion(DiffRegion);
+
+ /* Now get rid of the old visible region */
+ free_region(CalcWindow->Visible);
+ CalcWindow->Visible = NewRegion;
+
+ /* Show the difference if any */
+ //if (!is_region_empty(DiffRegion))
+ // SwmInvalidateRegion(CalcWindow, DiffRegion, NULL);
+
+ /* Free allocated temporary regions */
+ free_region(DiffRegion);
+ free_region(ParentRegion);
+}
+
+VOID
+NTAPI
+SwmClipAllWindows()
+{
+ PLIST_ENTRY Current;
+ PSWM_WINDOW Window;
+
+ /* Traverse the list to find our window */
Current = SwmWindows.Flink;
while(Current != &SwmWindows)
{
@@ -194,37 +286,8 @@
continue;
}
- /* Get window's region */
- WindowRegion = create_empty_region();
- set_region_rect(WindowRegion, &Window->Window);
-
- /* Region to mark invisible for this window = Update region X Window region */
- intersect_region(WindowRegion, WindowRegion, Region);
-
- /* Check if it's empty */
- if (!is_region_empty(WindowRegion))
- {
- DPRINT("Invalidating region\n");
- SwmDumpRegion(WindowRegion);
- DPRINT("of window %x\n", Window->hwnd);
-
- /* If it's not empty, subtract it from the source region */
- subtract_region(Region, Region, WindowRegion);
-
- /* And add it to this window's visible region */
- union_region(Window->Visible, Window->Visible, WindowRegion);
-
- /* Invalidate this region of target window */
- SwmInvalidateRegion(Window, WindowRegion, NULL);
-
- DPRINT("Rest of the update region is:\n");
- SwmDumpRegion(Region);
- }
-
- free_region(WindowRegion);
-
- /* If region to update became empty, quit */
- if (is_region_empty(Region)) break;
+ /* Recalculate visibility for this window */
+ SwmRecalculateVisibility(Window);
/* Advance to the next window */
Current = Current->Flink;
@@ -233,17 +296,13 @@
VOID
NTAPI
-SwmRecalculateVisibility(PSWM_WINDOW CalcWindow)
+SwmDrawAllWindows()
{
PLIST_ENTRY Current;
PSWM_WINDOW Window;
- struct region *Region = create_empty_region();
- struct region *WindowRegion = create_empty_region();
-
- set_region_rect(WindowRegion, &CalcWindow->Window);
-
- /* Compile a total region of visible regions of "higher" windows */
- Current = &CalcWindow->Entry;
+
+ /* Traverse the list to find our window */
+ Current = SwmWindows.Flink;
while(Current != &SwmWindows)
{
Window = CONTAINING_RECORD(Current, SWM_WINDOW, Entry);
@@ -252,25 +311,16 @@
if (Window->Hidden)
{
/* Advance to the next window */
- Current = Current->Blink;
+ Current = Current->Flink;
continue;
}
- union_region(Region, Region, Window->Visible);
-
- /* Advance to the previous window */
- Current = Current->Blink;
- }
-
- /* Crop the region against target window */
- intersect_region(Region, Region, WindowRegion);
-
- /* Subtract result from target window's visible region */
- subtract_region(CalcWindow->Visible, WindowRegion, Region);
-
- /* Free allocated temporary regions */
- free_region(Region);
- free_region(WindowRegion);
+ /* Draw its visible region */
+ SwmInvalidateRegion(Window, Window->Visible, NULL);
+
+ /* Advance to the next window */
+ Current = Current->Flink;
+ }
}
VOID
@@ -279,8 +329,8 @@
{
PSWM_WINDOW Win;
- DPRINT("SwmAddWindow %x\n", hWnd);
- DPRINT("rect (%d,%d)-(%d,%d)\n", WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom);
+ DPRINT1("SwmAddWindow %x\n", hWnd);
+ DPRINT1("rect (%d,%d)-(%d,%d)\n", WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom);
/* Acquire the lock */
SwmAcquire();
@@ -298,15 +348,16 @@
set_region_rect(Win->Visible, &Win->Window);
/* Now go through the list and remove this rect from all underlying windows visible region */
- SwmMarkInvisible(Win->Visible);
+ //SwmMarkInvisible(Win->Visible);
InsertHeadList(&SwmWindows, &Win->Entry);
/* Now ensure it is visible on screen */
SwmInvalidateRegion(Win, Win->Visible, &Win->Window);
+ SwmClipAllWindows();
+
//SwmDumpWindows();
- //SwmDebugDrawWindows();
/* Release the lock */
SwmRelease();
@@ -346,10 +397,10 @@
Desktop->Visible = create_empty_region();
set_region_rect(Desktop->Visible, &Desktop->Window);
- /* Now go through the list and remove this rect from all underlying windows visible region */
- SwmMarkInvisible(Desktop->Visible);
-
InsertTailList(&SwmWindows, &Desktop->Entry);
+
+ /* Calculate windows clipping */
+ SwmClipAllWindows();
/* Now ensure it is visible on screen */
SwmInvalidateRegion(Desktop, Desktop->Visible, &Desktop->Window);
@@ -394,7 +445,7 @@
/* Acquire the lock */
SwmAcquire();
- DPRINT("SwmRemoveWindow %x\n", hWnd);
+ DPRINT1("SwmRemoveWindow %x\n", hWnd);
/* Allocate entry */
Win = SwmFindByHwnd(hWnd);
@@ -410,12 +461,14 @@
RemoveEntryList(&Win->Entry);
/* Mark this region as visible in other window */
- SwmMarkVisible(Win->Visible);
+ //SwmMarkVisible(Win->Visible);
/* Free the entry */
free_region(Win->Visible);
ExFreePool(Win);
+ SwmClipAllWindows();
+
/* Release the lock */
SwmRelease();
}
@@ -450,7 +503,9 @@
SwmBringToFront(PSWM_WINDOW SwmWin)
{
PSWM_WINDOW Previous;
+#ifdef INCREMENTAL_CLIPPING
struct region *OldVisible;
+#endif
/* Save previous focus window */
Previous = SwmGetTopWindow();
@@ -470,6 +525,7 @@
/* Add it to the head of the list */
InsertHeadList(&SwmWindows, &SwmWin->Entry);
+#ifdef INCREMENTAL_CLIPPING
/* Subtract old visible from the new one to find region for updating */
OldVisible = create_empty_region();
set_region_rect(OldVisible, &SwmWin->Window);
@@ -492,6 +548,16 @@
/* Update previous window's visible region */
SwmRecalculateVisibility(Previous);
+#else
+ /* Make it fully visible */
+ free_region(SwmWin->Visible);
+ SwmWin->Visible = create_empty_region();
+ set_region_rect(SwmWin->Visible, &SwmWin->Window);
+
+ // TODO: Redraw only new parts!
+ SwmClipAllWindows();
+ SwmInvalidateRegion(SwmWin, SwmWin->Visible, NULL);
+#endif
}
VOID
@@ -530,8 +596,10 @@
SwmPosChanged(HWND hWnd, const RECT *WindowRect, const RECT *OldRect)
{
PSWM_WINDOW SwmWin;
+#ifdef INCREMENTAL_CLIPPING
struct region *NewRegion;
rectangle_t WinRect;
+#endif
/* Acquire the lock */
SwmAcquire();
@@ -555,12 +623,14 @@
SwmRelease();
return;
}
+//DPRINT1("rect (%d,%d)-(%d,%d)\n", TmpRect.left, TmpRect.top, TmpRect.right, TmpRect.bottom);
+ DPRINT1("SwmPosChanged hwnd %x, new rect (%d,%d)-(%d,%d)\n", hWnd, WindowRect->left, WindowRect->top, WindowRect->right, WindowRect->bottom);
SwmWin->Window.left = WindowRect->left;
SwmWin->Window.top = WindowRect->top;
SwmWin->Window.right = WindowRect->right;
SwmWin->Window.bottom = WindowRect->bottom;
-
+#ifdef INCREMENTAL_CLIPPING
//SwmDebugDrawWindows();
/* Assure the moving window is foreground */
@@ -587,6 +657,9 @@
/* Redraw window itself too */
//SwmInvalidateRegion(SwmWin, SwmWin->Visible, NULL);
+#else
+ SwmClipAllWindows();
+#endif
/* Release the lock */
SwmRelease();
@@ -597,6 +670,7 @@
SwmShowWindow(HWND hWnd, BOOLEAN Show)
{
PSWM_WINDOW Win;
+ struct region *OldRegion;
/* Acquire the lock */
SwmAcquire();
@@ -615,22 +689,28 @@
if (Show && Win->Hidden)
{
/* Change state from hidden to visible */
- DPRINT("Unhiding %x\n", Win->hwnd);
+ DPRINT1("Unhiding %x\n", Win->hwnd);
Win->Hidden = FALSE;
SwmBringToFront(Win);
}
else if (!Show && !Win->Hidden)
{
- DPRINT("Hiding %x\n", Win->hwnd);
+ DPRINT1("Hiding %x\n", Win->hwnd);
/* Change state from visible to hidden */
Win->Hidden = TRUE;
- /* Mark its region as visible */
- SwmMarkVisible(Win->Visible);
-
- /* Its visible region is now empty */
- free_region(Win->Visible);
+ /* Save its visible region */
+ OldRegion = Win->Visible;
+
+ /* Put an empty visible region */
Win->Visible = create_empty_region();
+
+ /* Recalculate clipping */
+ SwmClipAllWindows();
+
+ /* Show region which was taken by this window and free it */
+ SwmPaintRegion(OldRegion);
+ free_region(OldRegion);
}
/* Release the lock */