95 QMacAutoReleasePool pool;
96 QCocoaMenuItem *cocoaItem =
static_cast<QCocoaMenuItem *>(menuItem);
97 QCocoaMenuItem *beforeItem =
static_cast<QCocoaMenuItem *>(before);
101 int index = m_menuItems.indexOf(beforeItem);
104 qCWarning(lcQpaMenus) << beforeItem <<
"not in" << m_menuItems;
107 m_menuItems.insert(index, cocoaItem);
109 m_menuItems.append(cocoaItem);
112 insertNative(cocoaItem, beforeItem);
116 if (isVisible() && attachedItem().hidden) {
117 if (
auto *mb = qobject_cast<QCocoaMenuBar *>(menuParent()))
181 QMacAutoReleasePool pool;
182 QCocoaMenuItem *cocoaItem =
static_cast<QCocoaMenuItem *>(menuItem);
183 if (!m_menuItems.contains(cocoaItem)) {
184 qCWarning(lcQpaMenus) << m_menuItems <<
"does not contain" << cocoaItem;
188 if (cocoaItem->menuParent() ==
this)
189 cocoaItem->setMenuParent(
nullptr);
192 cocoaItem->setParentEnabled(
true);
194 m_menuItems.removeOne(cocoaItem);
195 if (!cocoaItem->isMerged()) {
196 if (m_nativeMenu != cocoaItem->nsItem().menu) {
197 qCWarning(lcQpaMenus) << cocoaItem <<
"does not belong to" << m_nativeMenu;
200 [m_nativeMenu removeItem:cocoaItem->nsItem()];
235 QMacAutoReleasePool pool;
236 QCocoaMenuItem *cocoaItem =
static_cast<QCocoaMenuItem *>(menuItem);
237 if (!m_menuItems.contains(cocoaItem)) {
238 qCWarning(lcQpaMenus) << cocoaItem <<
"does not belong to" <<
this;
242 const bool wasMerged = cocoaItem->isMerged();
243 NSMenuItem *oldItem = cocoaItem->nsItem();
244 NSMenuItem *syncedItem = cocoaItem->sync();
246 if (syncedItem != oldItem) {
250 oldItem.enabled = NO;
251 oldItem.hidden = YES;
252 oldItem.keyEquivalent = @
"";
253 oldItem.keyEquivalentModifierMask = NSEventModifierFlagCommand;
256 [m_nativeMenu removeItem:oldItem];
260 QCocoaMenuItem* beforeItem = itemOrNull(m_menuItems.indexOf(cocoaItem) + 1);
261 insertNative(cocoaItem, beforeItem);
273 if (QCocoaMenu *submenu = cocoaItem->menu())
274 submenu->setAttachedItem(syncedItem);
279 QMacAutoReleasePool pool;
281 bool previousIsSeparator =
true;
282 NSMenuItem *lastVisibleItem = nil;
284 for (NSMenuItem *item in m_nativeMenu.itemArray) {
285 if (item.separatorItem) {
287 bool hideItem = previousIsSeparator;
288 if (
auto *cocoaItem = qt_objc_cast<QCocoaNSMenuItem *>(item).platformMenuItem)
289 hideItem = previousIsSeparator || !cocoaItem->isVisible();
290 item.hidden = hideItem;
294 lastVisibleItem = item;
295 previousIsSeparator = lastVisibleItem.separatorItem;
300 if (lastVisibleItem && lastVisibleItem.separatorItem)
301 lastVisibleItem.hidden = YES;
303 for (
auto *item : std::as_const(m_menuItems)) {
304 if (!item->isSeparator())
333void QCocoaMenu::
showPopup(
const QWindow *parentWindow,
const QRect &targetRect,
const QPlatformMenuItem *item)
335 QMacAutoReleasePool pool;
337 QPointer<QCocoaMenu> guard =
this;
339 QPoint pos = QPoint(targetRect.left(), targetRect.top() + targetRect.height());
342 QPointer<QCocoaWindow> cocoaWindow = parentWindow ?
static_cast<
QCocoaWindow *>(parentWindow->handle()) :
nullptr;
343 NSView *view = cocoaWindow ? cocoaWindow->view() : nil;
344 NSMenuItem *nsItem = item ? ((QCocoaMenuItem *)item)->nsItem() : nil;
347 bool resetMenuParent =
false;
349 setMenuParent(cocoaWindow);
350 resetMenuParent =
true;
352 auto menuParentGuard = qScopeGuard([&]{
354 setMenuParent(
nullptr);
357 QScreen *screen =
nullptr;
359 screen = parentWindow->screen();
360 if (!screen && !QGuiApplication::screens().isEmpty())
361 screen = QGuiApplication::screens().at(0);
374 NSPopUpButtonCell *popupCell = [[[NSPopUpButtonCell alloc] initTextCell:@
"" pullsDown:NO]
376 popupCell.altersStateOfSelectedItem = NO;
377 popupCell.transparent = YES;
378 popupCell.menu = m_nativeMenu;
379 [popupCell selectItem:nsItem];
382 int availableHeight = cocoaScreen->availableGeometry().height();
383 const QPoint globalPos = cocoaWindow ? cocoaWindow->mapToGlobal(pos) : pos;
384 int menuHeight = m_nativeMenu.size.height;
385 if (globalPos.y() + menuHeight > availableHeight) {
390 float idx = ([m_nativeMenu indexOfItem:nsItem] + 1.0f) / m_nativeMenu.numberOfItems;
391 float heightBelowPos = (1.0 - idx) * menuHeight;
392 if (globalPos.y() + heightBelowPos > availableHeight)
393 pos.setY(pos.y() - globalPos.y() + availableHeight - heightBelowPos);
396 NSRect cellFrame = NSMakeRect(pos.x(), pos.y(), m_nativeMenu.minimumWidth, 10);
397 [popupCell performClickWithFrame:cellFrame inView:view];
400 NSPoint nsPos = NSMakePoint(pos.x() - 1, pos.y());
403 nsPos = [view convertPoint:nsPos toView:nil];
405 nsPos.y = screen->availableVirtualSize().height() - nsPos.y;
410 NSEvent *menuEvent = [NSEvent mouseEventWithType:NSEventTypeRightMouseDown
414 windowNumber:view ? view.window.windowNumber : 0
419 [NSMenu popUpContextMenu:m_nativeMenu withEvent:menuEvent forView:view];
421 [m_nativeMenu popUpMenuPositioningItem:nsItem atLocation:nsPos inView:nil];
426 menuParentGuard.dismiss();
432 if (cocoaWindow && !cocoaWindow->isForeignWindow())
433 [qnsview_cast(view) resetMouseButtons];
482 QMacAutoReleasePool pool;
484 m_parentEnabled = enabled;
485 if (!m_enabled && enabled)
488 for (
auto *item : std::as_const(m_menuItems)) {
489 if (QCocoaMenu *menu = item->menu())
490 menu->propagateEnabledState(enabled);
492 item->setParentEnabled(enabled);