View Issue Details
ID | Project | Category | View Status | Date Submitted | Last Update |
---|---|---|---|---|---|
0004846 | JEDI VCL | 00 JVCL Components | public | 2009-07-06 00:11 | 2012-02-29 16:53 |
Reporter | Moritz Beutel | Assigned To | obones | ||
Priority | normal | Severity | crash | Reproducibility | sometimes |
Status | resolved | Resolution | fixed | ||
Product Version | 3.36 | ||||
Target Version | Fixed in Version | 3.45 | |||
Summary | 0004846: [Unit JvDockVSNetStyle] TJvDockVSNetStyle.Timer can cause stack overflow on Vista/Aero | ||||
Description | TJvDockVSNetStyle.Timer has a nested function the calls itself recursively: // ----- function PointIsOnPopup(P: TPoint; GlobalCheck: Boolean): Boolean; const GW_ENABLEDPOPUP = 6; var Control: TWinControl; Handle: HWND; Rect: TRect; ActivePopupWindow: Boolean; begin Control := FindVCLWindow(P); Result := ControlIsOnPopup(Control); if not Result then begin // Check whether a popup window is currently displayed (hint, popup menu) Handle := WindowFromPoint(P); ActivePopupWindow := IsPopupWindow(Handle); if not ActivePopupWindow and GlobalCheck then begin Handle := GetWindow(Application.Handle, GW_ENABLEDPOPUP); ActivePopupWindow := IsPopupWindow(Handle); if not ActivePopupWindow then begin Handle := GetTopWindow(GetDesktopWindow); ActivePopupWindow := IsPopupWindow(Handle); end; end; if ActivePopupWindow then begin GetWindowRect(Handle, Rect); // Search for a control one pixel to the left; Dec(Rect.Left); Result := PointIsOnPopup(Rect.TopLeft, False); // <-- if not Result then begin // Search for a control one pixel to the Right; Inc(Rect.Right); Result := PointIsOnPopup(Point(Rect.Right, Rect.Top), False); // <-- end; end; end; end; // ----- I'm not entirely sure what caused this - it doesn't always reproduce, and I've never seen it on XP. On the first look, the function seems to miss a strong termination condition. I've mostly seen this happen when a modal message box is shown. My guess is that, on Vista, WindowFromPoint(Point(WindowRect.Left - 1, WindowRect.Top)) is probing the thick frame of the window it comes from, therefore returns exactly that window, which causes PointIsOnPopup() to never terminate. As for the solution, either the way of determining the right/left window must be adapted, or a termination condition should be included. (IMHO, the latter should happen in any case to prevent a stack overflow.) Reference: 0004305 (http://issuetracker.delphi-jedi.org/view.php?id=4305) | ||||
Tags | No tags attached. | ||||
|
Please someone with vista test this |
|
Suggested workaround attached as .diff file |
2010-06-10 03:11
|
JvDockVSNetStyle.pas.diff (1,876 bytes)
--- E:/Eigene Dateien/RAD Studio/Projekte/repository/3rdparty/jedi-svn/jvcl/run/JvDockVSNetStyle.pas Tue Jun 08 16:00:08 2010 +++ E:/Eigene Dateien/RAD Studio/Projekte/repository/3rdparty/Weaver/jvcl/run/JvDockVSNetStyle.pas Mon Mar 29 12:30:30 2010 @@ -2532,11 +2532,11 @@ LStyle := GetWindowLong(Handle, GWL_STYLE); Result := WS_POPUP and LSTYLE <> 0; end; end; - function PointIsOnPopup(P: TPoint; GlobalCheck: Boolean): Boolean; + function PointIsOnPopup(P: TPoint; GlobalCheck: Boolean; Recurse: Boolean): Boolean; const GW_ENABLEDPOPUP = 6; var Control: TWinControl; Handle: HWND; @@ -2559,21 +2559,21 @@ Handle := GetTopWindow(GetDesktopWindow); ActivePopupWindow := IsPopupWindow(Handle); end; end; - if ActivePopupWindow then + if Recurse and ActivePopupWindow then begin GetWindowRect(Handle, Rect); // Search for a control one pixel to the left; Dec(Rect.Left); - Result := PointIsOnPopup(Rect.TopLeft, False); + Result := PointIsOnPopup(Rect.TopLeft, False, False); if not Result then begin // Search for a control one pixel to the Right; Inc(Rect.Right); - Result := PointIsOnPopup(Point(Rect.Right, Rect.Top), False); + Result := PointIsOnPopup(Point(Rect.Right, Rect.Top), False, False); end; end; end; end; @@ -2585,11 +2585,11 @@ if (csDesigning in ComponentState) or not ChannelOption.MouseleaveHide or ((GetAsyncKeyState(VK_LBUTTON) and $8000) <> 0) then Exit; GetCursorPos(P); - if PointIsOnPopup(P, True) then + if PointIsOnPopup(P, True, True) then begin { Reset timer } FCurrentTimer := ChannelOption.HideHoldTime; Exit; end; |
|
Thanks, this now in SVN |
Date Modified | Username | Field | Change |
---|---|---|---|
2009-07-06 00:11 | Moritz Beutel | New Issue | |
2009-07-06 14:03 | obones | Relationship added | related to 0004305 |
2009-07-06 14:15 | obones | Note Added: 0015769 | |
2009-07-06 14:15 | obones | Status | new => acknowledged |
2010-06-10 03:11 | Moritz Beutel | Note Added: 0017485 | |
2010-06-10 03:11 | Moritz Beutel | File Added: JvDockVSNetStyle.pas.diff | |
2010-10-08 15:48 | obones | Note Added: 0017796 | |
2010-10-08 15:48 | obones | Status | acknowledged => resolved |
2010-10-08 15:48 | obones | Fixed in Version | => Daily / SVN |
2010-10-08 15:48 | obones | Resolution | open => fixed |
2010-10-08 15:48 | obones | Assigned To | => obones |
2012-02-29 16:53 | obones | Fixed in Version | Daily / SVN => 3.45 |