BMenu: use std::stable_sort to implement SortItems

This fixes two problems:

- Use of a stable sorting algorithm makes sure that the relative
  position between items that compare equal are not modified
- More importantly, the compare function in BList passes a
  pointer-to-pointer (in this case a BMenuItem**) and this was masked by
  the casts due to BList lack of type safety. So, BMenu::SortItems was
  not working at all when trying to use it as its prototype would imply.

NetworkStatus and Network preferences worked around this by doing the
extra dereferencing in their compare functions. I did not find any
other places in Haiku where this function is used (it was introduced
specifically for this in hrev55562). All 3rd party code that had a
similar workaround will have to be fixed to remove it (if there is
anything using that function).

Change-Id: Ia78fd1363f2c012f6eff6f9a47e8b3aac2752ebd
Reviewed-on: https://review.haiku-os.org/c/haiku/+/7356
Reviewed-by: Niels Sascha Reedijk <niels.reedijk@gmail.com>
This commit is contained in:
PulkoMandy 2024-01-28 14:29:22 +01:00 committed by Adrien Destugues
parent 8446d3b9b5
commit 67380402ab
2 changed files with 7 additions and 3 deletions

View File

@ -103,8 +103,8 @@ WirelessNetworkMenuItem::DrawRadioIcon()
WirelessNetworkMenuItem::CompareSignalStrength(const BMenuItem* a,
const BMenuItem* b)
{
WirelessNetworkMenuItem* aItem = *(WirelessNetworkMenuItem**)a;
WirelessNetworkMenuItem* bItem = *(WirelessNetworkMenuItem**)b;
WirelessNetworkMenuItem* aItem = (WirelessNetworkMenuItem*)a;
WirelessNetworkMenuItem* bItem = (WirelessNetworkMenuItem*)b;
wireless_network aNetwork = aItem->Network();
wireless_network bNetwork = bItem->Network();

View File

@ -1451,7 +1451,11 @@ BMenu::SetTrackingHook(menu_tracking_hook func, void* state)
void
BMenu::SortItems(int (*compare)(const BMenuItem*, const BMenuItem*))
{
fItems.SortItems((int (*)(const void*, const void*))compare);
BMenuItem** begin = (BMenuItem**)fItems.Items();
BMenuItem** end = begin + fItems.CountItems();
std::stable_sort(begin, end, compare);
InvalidateLayout();
if (Window() != NULL && !Window()->IsHidden() && LockLooper()) {
_LayoutItems(0);