@@ -2860,122 +2860,29 @@ static BOOL MENU_InitPopup( PWND pWndOwner, PMENU menu, UINT flags )
2860
2860
return TRUE;
2861
2861
}
2862
2862
2863
-
2864
- #define SHOW_DEBUGRECT 0
2865
-
2866
- #if SHOW_DEBUGRECT
2867
- static void DebugRect (const RECT * rectl , COLORREF color )
2868
- {
2869
- HBRUSH brush ;
2870
- RECT rr ;
2871
- HDC hdc ;
2872
-
2873
- if (!rectl )
2874
- return ;
2875
-
2876
- hdc = UserGetDCEx (NULL , 0 , DCX_USESTYLE );
2877
-
2878
- brush = IntGdiCreateSolidBrush (color );
2879
-
2880
- rr = * rectl ;
2881
- RECTL_vInflateRect (& rr , 1 , 1 );
2882
- FrameRect (hdc , rectl , brush );
2883
- FrameRect (hdc , & rr , brush );
2884
-
2885
- NtGdiDeleteObjectApp (brush );
2886
- UserReleaseDC (NULL , hdc , TRUE);
2887
- }
2888
-
2889
- static void DebugPoint (INT x , INT y , COLORREF color )
2890
- {
2891
- RECT rr = {x , y , x , y };
2892
- DebugRect (& rr , color );
2893
- }
2894
- #endif
2895
-
2896
- static BOOL RECTL_Intersect (const RECT * pRect , INT x , INT y , UINT width , UINT height )
2897
- {
2898
- RECT other = {x , y , x + width , y + height };
2899
- RECT dum ;
2900
-
2901
- return RECTL_bIntersectRect (& dum , pRect , & other );
2902
- }
2903
-
2904
- static BOOL MENU_MoveRect (UINT flags , INT * x , INT * y , INT width , INT height , const RECT * pExclude , PMONITOR monitor )
2905
- {
2906
- /* Figure out if we should move vertical or horizontal */
2907
- if (flags & TPM_VERTICAL )
2908
- {
2909
- /* Move in the vertical direction: TPM_BOTTOMALIGN means drop it above, otherways drop it below */
2910
- if (flags & TPM_BOTTOMALIGN )
2911
- {
2912
- if (pExclude -> top - height >= monitor -> rcMonitor .top )
2913
- {
2914
- * y = pExclude -> top - height ;
2915
- return TRUE;
2916
- }
2917
- }
2918
- else
2919
- {
2920
- if (pExclude -> bottom + height < monitor -> rcMonitor .bottom )
2921
- {
2922
- * y = pExclude -> bottom ;
2923
- return TRUE;
2924
- }
2925
- }
2926
- }
2927
- else
2928
- {
2929
- /* Move in the horizontal direction: TPM_RIGHTALIGN means drop it to the left, otherways go right */
2930
- if (flags & TPM_RIGHTALIGN )
2931
- {
2932
- if (pExclude -> left - width >= monitor -> rcMonitor .left )
2933
- {
2934
- * x = pExclude -> left - width ;
2935
- return TRUE;
2936
- }
2937
- }
2938
- else
2939
- {
2940
- if (pExclude -> right + width < monitor -> rcMonitor .right )
2941
- {
2942
- * x = pExclude -> right ;
2943
- return TRUE;
2944
- }
2945
- }
2946
- }
2947
- return FALSE;
2948
- }
2949
-
2950
2863
/***********************************************************************
2951
2864
* MenuShowPopup
2952
2865
*
2953
2866
* Display a popup menu.
2954
2867
*/
2955
2868
static BOOL FASTCALL MENU_ShowPopup (PWND pwndOwner , PMENU menu , UINT id , UINT flags ,
2956
- INT x , INT y , const RECT * pExclude )
2869
+ INT x , INT y , INT xanchor , INT yanchor )
2957
2870
{
2958
2871
UINT width , height ;
2959
- POINT ptx ;
2872
+ POINT pt ;
2960
2873
PMONITOR monitor ;
2961
2874
PWND pWnd ;
2962
2875
USER_REFERENCE_ENTRY Ref ;
2963
- BOOL bIsPopup = (flags & TPM_POPUPMENU ) != 0 ;
2964
2876
2965
- TRACE ("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x\n" ,
2966
- pwndOwner , menu , id , x , y );
2877
+ TRACE ("owner=%p menu=%p id=0x%04x x=0x%04x y=0x%04x xa=0x%04x ya=0x%04x \n" ,
2878
+ pwndOwner , menu , id , x , y , xanchor , yanchor );
2967
2879
2968
2880
if (menu -> iItem != NO_SELECTED_ITEM )
2969
2881
{
2970
2882
menu -> rgItems [menu -> iItem ].fState &= ~(MF_HILITE |MF_MOUSESELECT );
2971
2883
menu -> iItem = NO_SELECTED_ITEM ;
2972
2884
}
2973
2885
2974
- #if SHOW_DEBUGRECT
2975
- if (pExclude )
2976
- DebugRect (pExclude , RGB (255 , 0 , 0 ));
2977
- #endif
2978
-
2979
2886
menu -> dwArrowsOn = 0 ;
2980
2887
MENU_PopupMenuCalcSize (menu , pwndOwner );
2981
2888
@@ -2984,102 +2891,67 @@ static BOOL FASTCALL MENU_ShowPopup(PWND pwndOwner, PMENU menu, UINT id, UINT fl
2984
2891
width = menu -> cxMenu + UserGetSystemMetrics (SM_CXBORDER );
2985
2892
height = menu -> cyMenu + UserGetSystemMetrics (SM_CYBORDER );
2986
2893
2987
- if (flags & TPM_LAYOUTRTL )
2988
- flags ^= TPM_RIGHTALIGN ;
2989
-
2990
- if (flags & TPM_RIGHTALIGN )
2991
- x -= width ;
2992
- if (flags & TPM_CENTERALIGN )
2993
- x -= width / 2 ;
2994
-
2995
- if (flags & TPM_BOTTOMALIGN )
2996
- y -= height ;
2997
- if (flags & TPM_VCENTERALIGN )
2998
- y -= height / 2 ;
2999
-
3000
2894
/* FIXME: should use item rect */
3001
- ptx .x = x ;
3002
- ptx .y = y ;
3003
- #if SHOW_DEBUGRECT
3004
- DebugPoint (x , y , RGB (0 , 0 , 255 ));
3005
- #endif
3006
- monitor = UserMonitorFromPoint ( ptx , MONITOR_DEFAULTTONEAREST );
2895
+ pt .x = x ;
2896
+ pt .y = y ;
2897
+ monitor = UserMonitorFromPoint ( pt , MONITOR_DEFAULTTONEAREST );
3007
2898
3008
- /* We are off the right side of the screen */
3009
- if (x + width > monitor -> rcMonitor .right )
3010
- {
3011
- if ((x - width ) < monitor -> rcMonitor .left || x >= monitor -> rcMonitor .right )
3012
- x = monitor -> rcMonitor .right - width ;
3013
- else
3014
- x -= width ;
3015
- }
2899
+ if (flags & TPM_LAYOUTRTL )
2900
+ flags ^= TPM_RIGHTALIGN ;
3016
2901
3017
- /* We are off the left side of the screen */
3018
- if (x < monitor -> rcMonitor .left )
3019
- {
3020
- /* Re-orient the menu around the x-axis */
3021
- x += width ;
2902
+ if ( flags & TPM_RIGHTALIGN ) x -= width ;
2903
+ if ( flags & TPM_CENTERALIGN ) x -= width / 2 ;
3022
2904
3023
- if (x < monitor -> rcMonitor .left || x >= monitor -> rcMonitor .right || bIsPopup )
3024
- x = monitor -> rcMonitor .left ;
3025
- }
2905
+ if ( flags & TPM_BOTTOMALIGN ) y -= height ;
2906
+ if ( flags & TPM_VCENTERALIGN ) y -= height / 2 ;
3026
2907
3027
- /* Same here, but then the top */
3028
- if (y < monitor -> rcMonitor .top )
2908
+ if ( x + width > monitor -> rcMonitor .right )
3029
2909
{
3030
- y += height ;
2910
+ if ( xanchor && x >= width - xanchor )
2911
+ x -= width - xanchor ;
3031
2912
3032
- if (y < monitor -> rcMonitor .top || y >= monitor -> rcMonitor .bottom || bIsPopup )
3033
- y = monitor -> rcMonitor .top ;
2913
+ if ( x + width > monitor -> rcMonitor .right )
2914
+ {
2915
+ /* If we would flip around our origin, would we go off screen on the other side?
2916
+ Or is our origin itself too far to the right already? */
2917
+ if (x - width < monitor -> rcMonitor .left || x > monitor -> rcMonitor .right )
2918
+ x = monitor -> rcMonitor .right - width ;
2919
+ else
2920
+ x -= width ;
2921
+ }
3034
2922
}
3035
-
3036
- /* And the bottom */
3037
- if (y + height > monitor -> rcMonitor .bottom )
2923
+ if ( x < monitor -> rcMonitor .left )
3038
2924
{
3039
- if ((y - height ) < monitor -> rcMonitor .top || y >= monitor -> rcMonitor .bottom || bIsPopup )
3040
- y = monitor -> rcMonitor .bottom - height ;
2925
+ /* If we would flip around our origin, would we go off screen on the other side? */
2926
+ if (x + width > monitor -> rcMonitor .right )
2927
+ x = monitor -> rcMonitor .left ;
3041
2928
else
3042
- y -= height ;
2929
+ x += width ;
3043
2930
}
3044
2931
3045
- if ( pExclude )
2932
+ if ( y + height > monitor -> rcMonitor . bottom )
3046
2933
{
3047
- RECT Cleaned ;
2934
+ if ( yanchor && y >= height + yanchor )
2935
+ y -= height + yanchor ;
3048
2936
3049
- if (RECTL_bIntersectRect (& Cleaned , pExclude , & monitor -> rcMonitor ) &&
3050
- RECTL_Intersect (& Cleaned , x , y , width , height ))
2937
+ if ( y + height > monitor -> rcMonitor .bottom )
3051
2938
{
3052
- UINT flag_mods [] = {
3053
- 0 , /* First try the 'normal' way */
3054
- TPM_BOTTOMALIGN | TPM_RIGHTALIGN , /* Then try the opposite side */
3055
- TPM_VERTICAL , /* Then swap horizontal / vertical */
3056
- TPM_BOTTOMALIGN | TPM_RIGHTALIGN | TPM_VERTICAL , /* Then the other side again (still swapped hor/ver) */
3057
- };
3058
- UINT n ;
3059
- for (n = 0 ; n < RTL_NUMBER_OF (flag_mods ); ++ n )
3060
- {
3061
- INT tx = x ;
3062
- INT ty = y ;
3063
-
3064
- /* Try to move a bit around */
3065
- if (MENU_MoveRect (flags ^ flag_mods [n ], & tx , & ty , width , height , & Cleaned , monitor ) &&
3066
- !RECTL_Intersect (& Cleaned , tx , ty , width , height ))
3067
- {
3068
- x = tx ;
3069
- y = ty ;
3070
- break ;
3071
- }
3072
- }
3073
- /* If none worked, we go with the original x/y */
2939
+ /* If we would flip around our origin, would we go off screen on the other side?
2940
+ Or is our origin itself too far to the bottom already? */
2941
+ if (y - height < monitor -> rcMonitor .top || y > monitor -> rcMonitor .bottom )
2942
+ y = monitor -> rcMonitor .bottom - height ;
2943
+ else
2944
+ y -= height ;
3074
2945
}
3075
2946
}
3076
-
3077
- #if SHOW_DEBUGRECT
2947
+ if ( y < monitor -> rcMonitor .top )
3078
2948
{
3079
- RECT rr = {x , y , x + width , y + height };
3080
- DebugRect (& rr , RGB (0 , 255 , 0 ));
2949
+ /* If we would flip around our origin, would we go off screen on the other side? */
2950
+ if (y + height > monitor -> rcMonitor .bottom )
2951
+ y = monitor -> rcMonitor .top ;
2952
+ else
2953
+ y += height ;
3081
2954
}
3082
- #endif
3083
2955
3084
2956
pWnd = ValidateHwndNoErr ( menu -> hWnd );
3085
2957
@@ -3327,7 +3199,7 @@ static void FASTCALL MENU_HideSubPopups(PWND pWndOwner, PMENU Menu,
3327
3199
*/
3328
3200
static PMENU FASTCALL MENU_ShowSubPopup (PWND WndOwner , PMENU Menu , BOOL SelectFirst , UINT Flags )
3329
3201
{
3330
- RECT Rect , ParentRect ;
3202
+ RECT Rect ;
3331
3203
ITEM * Item ;
3332
3204
HDC Dc ;
3333
3205
PWND pWnd ;
@@ -3362,13 +3234,6 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
3362
3234
3363
3235
pWnd = ValidateHwndNoErr (Menu -> hWnd );
3364
3236
3365
- /* Grab the rect of our (entire) parent menu, so we can try to not overlap it */
3366
- if (!IntGetWindowRect (pWnd , & ParentRect ))
3367
- {
3368
- ERR ("No pWnd\n" );
3369
- ParentRect = Rect ;
3370
- }
3371
-
3372
3237
/* correct item if modified as a reaction to WM_INITMENUPOPUP message */
3373
3238
if (!(Item -> fState & MF_HILITE ))
3374
3239
{
@@ -3445,7 +3310,7 @@ static PMENU FASTCALL MENU_ShowSubPopup(PWND WndOwner, PMENU Menu, BOOL SelectFi
3445
3310
MENU_InitPopup ( WndOwner , Item -> spSubMenu , Flags );
3446
3311
3447
3312
MENU_ShowPopup ( WndOwner , Item -> spSubMenu , Menu -> iItem , Flags ,
3448
- Rect .left , Rect .top , & ParentRect );
3313
+ Rect .left , Rect .top , Rect . right , Rect . bottom );
3449
3314
if (SelectFirst )
3450
3315
{
3451
3316
MENU_MoveSelection (WndOwner , Item -> spSubMenu , ITEM_NEXT );
@@ -4045,7 +3910,7 @@ static void FASTCALL MENU_KeyRight(MTRACKER *pmt, UINT Flags, UINT msg)
4045
3910
* Menu tracking code.
4046
3911
*/
4047
3912
static INT FASTCALL MENU_TrackMenu (PMENU pmenu , UINT wFlags , INT x , INT y ,
4048
- PWND pwnd )
3913
+ PWND pwnd , const RECT * lprect )
4049
3914
{
4050
3915
MSG msg ;
4051
3916
BOOL fRemove ;
@@ -4068,8 +3933,9 @@ static INT FASTCALL MENU_TrackMenu(PMENU pmenu, UINT wFlags, INT x, INT y,
4068
3933
mt .Pt .x = x ;
4069
3934
mt .Pt .y = y ;
4070
3935
4071
- TRACE ("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x\n" ,
4072
- UserHMGetHandle (pmenu ), wFlags , x , y , UserHMGetHandle (pwnd ));
3936
+ TRACE ("MTM : hmenu=%p flags=0x%08x (%d,%d) hwnd=%x (%ld,%ld)-(%ld,%ld)\n" ,
3937
+ UserHMGetHandle (pmenu ), wFlags , x , y , UserHMGetHandle (pwnd ), lprect ? lprect -> left : 0 , lprect ? lprect -> top : 0 ,
3938
+ lprect ? lprect -> right : 0 , lprect ? lprect -> bottom : 0 );
4073
3939
4074
3940
pti -> MessageQueue -> QF_flags &= ~QF_ACTIVATIONCHANGE ;
4075
3941
@@ -4480,7 +4346,7 @@ VOID MENU_TrackMouseMenuBar( PWND pWnd, ULONG ht, POINT pt)
4480
4346
MENU_InitTracking (pWnd , pMenu , FALSE, wFlags );
4481
4347
/* fetch the window menu again, it may have changed */
4482
4348
pMenu = (ht == HTSYSMENU ) ? get_win_sys_menu ( UserHMGetHandle (pWnd ) ) : IntGetMenu ( UserHMGetHandle (pWnd ) );
4483
- MENU_TrackMenu (pMenu , wFlags , pt .x , pt .y , pWnd );
4349
+ MENU_TrackMenu (pMenu , wFlags , pt .x , pt .y , pWnd , NULL );
4484
4350
MENU_ExitTracking (pWnd , FALSE, wFlags );
4485
4351
}
4486
4352
}
@@ -4544,7 +4410,7 @@ VOID MENU_TrackKbdMenuBar(PWND pwnd, UINT wParam, WCHAR wChar)
4544
4410
}
4545
4411
4546
4412
track_menu :
4547
- MENU_TrackMenu ( TrackMenu , wFlags , 0 , 0 , pwnd );
4413
+ MENU_TrackMenu ( TrackMenu , wFlags , 0 , 0 , pwnd , NULL );
4548
4414
MENU_ExitTracking ( pwnd , FALSE, wFlags );
4549
4415
}
4550
4416
@@ -4586,8 +4452,9 @@ BOOL WINAPI IntTrackPopupMenuEx( PMENU menu, UINT wFlags, int x, int y,
4586
4452
if (menu -> fFlags & MNF_SYSMENU )
4587
4453
MENU_InitSysMenuPopup ( menu , pWnd -> style , pWnd -> pcls -> style , HTSYSMENU );
4588
4454
4589
- if (MENU_ShowPopup (pWnd , menu , 0 , wFlags | TPM_POPUPMENU , x , y , lpTpm ? & lpTpm -> rcExclude : NULL ))
4590
- ret = MENU_TrackMenu ( menu , wFlags | TPM_POPUPMENU , 0 , 0 , pWnd );
4455
+ if (MENU_ShowPopup (pWnd , menu , 0 , wFlags , x , y , 0 , 0 ))
4456
+ ret = MENU_TrackMenu ( menu , wFlags | TPM_POPUPMENU , 0 , 0 , pWnd ,
4457
+ lpTpm ? & lpTpm -> rcExclude : NULL );
4591
4458
else
4592
4459
{
4593
4460
MsqSetStateWindow (pti , MSQ_STATE_MENUOWNER , NULL );
0 commit comments