Fix context menu (right click) position

Was bound to mouse position before, is bound to item position now.
This commit is contained in:
Peter Kirmeier 2023-08-31 21:09:58 +02:00
parent e6ede5233b
commit f67662cc45
3 changed files with 60 additions and 46 deletions

View file

@ -7,7 +7,6 @@ namespace SystemTrayMenu.Business
using System;
using System.Windows.Input;
using SystemTrayMenu.DataClasses;
using SystemTrayMenu.DllImports;
using SystemTrayMenu.UserInterface;
using SystemTrayMenu.Utilities;
using static SystemTrayMenu.Helpers.GlobalHotkeys;
@ -125,7 +124,7 @@ namespace SystemTrayMenu.Business
case Key.Apps:
if (modifiers == ModifierKeys.None)
{
focussedMenu?.SelectedItem?.OpenShellContextMenu(NativeMethods.Screen.CursorPosition);
focussedMenu?.SelectedItem?.OpenShellContextMenu();
}
break;

View file

@ -269,8 +269,17 @@ namespace SystemTrayMenu.DataClasses
}
}
internal void OpenShellContextMenu(Point position)
internal void OpenShellContextMenu()
{
Point position = default;
if (Owner != null)
{
Point positionChild = Owner.GetRelativeDataGridViewChildPosition(this);
Point positionDgv = Owner.GetRelativeChildPositionTo(Owner.GetDataGridView());
position = new Point(Owner.Left + positionDgv.X + positionChild.X, Owner.Top + positionDgv.Y + positionChild.Y);
}
if (IsPointingToFolder)
{
ShellContextMenu.OpenShellContextMenu(new DirectoryInfo(Path), position);

View file

@ -729,49 +729,10 @@ namespace SystemTrayMenu.UserInterface
y = originLocation.Y;
// Set position on same height as the selected row from predecessor
ListView dgv = menuPredecessor.GetDataGridView()!;
RowData? trigger = RowDataParent;
if (trigger != null)
{
// When scrolled, we have to reduce the index number as we calculate based on visual tree
int startIndex = 0;
double offset = 0D;
if (VisualTreeHelper.GetChild(dgv, 0) is Decorator { Child: ScrollViewer scrollViewer })
{
startIndex = (int)scrollViewer.VerticalOffset;
if (trigger.RowIndex < startIndex)
{
// calculate position above starting point
for (int i = trigger.RowIndex; i < startIndex; i++)
{
ListViewItem? item = dgv.FindVisualChildOfType<ListViewItem>(i);
if (item != null)
{
offset -= item.ActualHeight;
}
}
}
}
if (startIndex < trigger.RowIndex)
{
// calculate position below starting point
// outer loop check for max RowIndex, independend of currently active filter
// inner loop check for filtered and shown items
for (int i = startIndex; i < trigger.RowIndex; i++)
{
ListViewItem? item = dgv.FindVisualChildOfType<ListViewItem>(i);
if (item != null)
{
if (((RowData)item.Content).RowIndex >= trigger.RowIndex)
{
break;
}
offset += item.ActualHeight;
}
}
}
double offset = menuPredecessor.GetRelativeDataGridViewChildPosition(trigger).Y;
if (offset < 0)
{
@ -780,6 +741,7 @@ namespace SystemTrayMenu.UserInterface
}
else
{
ListView dgv = menuPredecessor.GetDataGridView();
double offsetList = menuPredecessor.GetRelativeChildPositionTo(dgv).Y;
offsetList += dgv.ActualHeight;
if (offsetList < offset)
@ -832,6 +794,52 @@ namespace SystemTrayMenu.UserInterface
}
}
internal Point GetRelativeDataGridViewChildPosition(RowData rowData)
{
// When scrolled, we have to reduce the index number as we calculate based on visual tree
int rowIndex = rowData.RowIndex;
int startIndex = 0;
double offset = 0D;
if (VisualTreeHelper.GetChild(dgv, 0) is Decorator { Child: ScrollViewer scrollViewer })
{
startIndex = (int)scrollViewer.VerticalOffset;
if (rowIndex < startIndex)
{
// calculate position above starting point
for (int i = rowIndex; i < startIndex; i++)
{
ListViewItem? item = dgv.FindVisualChildOfType<ListViewItem>(i);
if (item != null)
{
offset -= item.ActualHeight;
}
}
}
}
if (startIndex < rowIndex)
{
// calculate position below starting point
// outer loop check for max RowIndex, independend of currently active filter
// inner loop check for filtered and shown items
for (int i = startIndex; i < rowIndex; i++)
{
ListViewItem? item = dgv.FindVisualChildOfType<ListViewItem>(i);
if (item != null)
{
if (((RowData)item.Content).RowIndex >= rowIndex)
{
break;
}
offset += item.ActualHeight;
}
}
}
return new(0D, offset);
}
private static bool Filter_Default(RowData itemData)
{
if (Settings.Default.ShowOnlyAsSearchResult && itemData.IsAdditionalItem)
@ -1147,9 +1155,7 @@ namespace SystemTrayMenu.UserInterface
// Prevent any use of MouseEnter/MouseLeave while the menu is open.
// TODO: Find root case and fix this properly.
isShellContextMenuOpen = true;
var position = Mouse.GetPosition(this);
position.Offset(Left, Top);
itemData.OpenShellContextMenu(position);
itemData.OpenShellContextMenu();
isShellContextMenuOpen = false;
}
}