Skip to content

Commit 868cb03

Browse files
committed
Fix right-click context menu in search entry
Fixes #13416 The menu search field didn't support right-click copy/paste properly. Users could only paste with Ctrl+V keyboard shortcut. Changes: - Add CinnamonEntry.addContextMenu() to enable right-click context menu - Prevent context menu from grabbing modal focus (shouldGrab = false) - Close context menu when main menu closes - Extend _eventIsOnActiveMenu to treat context menu as part of active menu - Add manual hover effect using mouse position polling and CSS pseudo-class (required because MenuManager blocks normal hover events)
1 parent 6113ff7 commit 868cb03

1 file changed

Lines changed: 49 additions & 0 deletions

File tree

files/usr/share/cinnamon/applets/[email protected]/applet.js

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2580,6 +2580,55 @@ class CinnamonMenuApplet extends Applet.TextIconApplet {
25802580
});
25812581
this.searchEntry.add_accessible_state(Atk.StateType.EDITABLE);
25822582
CinnamonEntry.addContextMenu(this.searchEntry);
2583+
this.searchEntry._menuManager.shouldGrab = false;
2584+
2585+
// Close the search entry context menu when main menu closes
2586+
this.menu.connect('open-state-changed', (menu, open) => {
2587+
if (!open && this.searchEntry._menu.isOpen) {
2588+
this.searchEntry._menu.close();
2589+
}
2590+
});
2591+
2592+
// Extend _eventIsOnActiveMenu to include the search entry context menu
2593+
// This prevents the main menu from closing when clicking on the context menu
2594+
let originalEventIsOnActiveMenu = this.menuManager._eventIsOnActiveMenu.bind(this.menuManager);
2595+
this.menuManager._eventIsOnActiveMenu = (event) => {
2596+
if (this.searchEntry._menu.isOpen &&
2597+
this.searchEntry._menu.actor.contains(event.get_source())) {
2598+
return true;
2599+
}
2600+
return originalEventIsOnActiveMenu(event);
2601+
};
2602+
2603+
// Manual hover effect using direct style pseudo-class (no signals)
2604+
let contextMenu = this.searchEntry._menu;
2605+
let contextMenuItems = [contextMenu._copyItem, contextMenu._pasteItem];
2606+
2607+
let updateHoverState = () => {
2608+
if (!contextMenu.isOpen) {
2609+
for (let item of contextMenuItems) {
2610+
item.actor.change_style_pseudo_class('active', false);
2611+
}
2612+
return true;
2613+
}
2614+
2615+
let [mouseX, mouseY] = global.get_pointer();
2616+
for (let item of contextMenuItems) {
2617+
let [itemX, itemY] = item.actor.get_transformed_position();
2618+
let [width, height] = item.actor.get_size();
2619+
let isHovered = (mouseX >= itemX && mouseX <= itemX + width &&
2620+
mouseY >= itemY && mouseY <= itemY + height);
2621+
item.actor.change_style_pseudo_class('active', isHovered);
2622+
}
2623+
return true;
2624+
};
2625+
2626+
// Start hover polling when main menu opens
2627+
this.menu.connect('open-state-changed', (menu, open) => {
2628+
if (open) {
2629+
Mainloop.timeout_add(50, updateHoverState);
2630+
}
2631+
});
25832632

25842633
this.searchEntry.set_secondary_icon(this._searchInactiveIcon);
25852634
this.searchActive = false;

0 commit comments

Comments
 (0)