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/winent... ============================================================================== --- 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/win32... ============================================================================== --- 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 */