| 
									
										
										
										
											2023-01-05 13:25:55 +01:00
										 |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*  godot_menu_delegate.mm                                                */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /*                         This file is part of:                          */ | 
					
						
							|  |  |  | /*                             GODOT ENGINE                               */ | 
					
						
							|  |  |  | /*                        https://godotengine.org                         */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							|  |  |  | /* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */ | 
					
						
							|  |  |  | /* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur.                  */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* Permission is hereby granted, free of charge, to any person obtaining  */ | 
					
						
							|  |  |  | /* a copy of this software and associated documentation files (the        */ | 
					
						
							|  |  |  | /* "Software"), to deal in the Software without restriction, including    */ | 
					
						
							|  |  |  | /* without limitation the rights to use, copy, modify, merge, publish,    */ | 
					
						
							|  |  |  | /* distribute, sublicense, and/or sell copies of the Software, and to     */ | 
					
						
							|  |  |  | /* permit persons to whom the Software is furnished to do so, subject to  */ | 
					
						
							|  |  |  | /* the following conditions:                                              */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* The above copyright notice and this permission notice shall be         */ | 
					
						
							|  |  |  | /* included in all copies or substantial portions of the Software.        */ | 
					
						
							|  |  |  | /*                                                                        */ | 
					
						
							|  |  |  | /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,        */ | 
					
						
							|  |  |  | /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF     */ | 
					
						
							|  |  |  | /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */ | 
					
						
							|  |  |  | /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY   */ | 
					
						
							|  |  |  | /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,   */ | 
					
						
							|  |  |  | /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE      */ | 
					
						
							|  |  |  | /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                 */ | 
					
						
							|  |  |  | /**************************************************************************/ | 
					
						
							| 
									
										
										
										
											2022-08-31 11:11:52 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | #include "godot_menu_delegate.h" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "display_server_macos.h" | 
					
						
							|  |  |  | #include "godot_menu_item.h" | 
					
						
							|  |  |  | #include "key_mapping_macos.h" | 
					
						
							| 
									
										
										
										
											2024-01-19 19:41:01 +02:00
										 |  |  | #include "native_menu_macos.h" | 
					
						
							| 
									
										
										
										
											2022-08-31 11:11:52 +03:00
										 |  |  | 
 | 
					
						
							|  |  |  | @implementation GodotMenuDelegate | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - (void)doNothing:(id)sender { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-05 10:33:28 +03:00
										 |  |  | - (void)menuWillOpen:(NSMenu *)menu { | 
					
						
							| 
									
										
										
										
											2024-01-19 19:41:01 +02:00
										 |  |  | 	if (NativeMenu::get_singleton()) { | 
					
						
							|  |  |  | 		NativeMenuMacOS *nmenu = (NativeMenuMacOS *)NativeMenu::get_singleton(); | 
					
						
							|  |  |  | 		nmenu->_menu_open(menu); | 
					
						
							| 
									
										
										
										
											2023-07-11 11:17:35 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-06-05 10:33:28 +03:00
										 |  |  | - (void)menuNeedsUpdate:(NSMenu *)menu { | 
					
						
							|  |  |  | 	if (NativeMenu::get_singleton()) { | 
					
						
							|  |  |  | 		NativeMenuMacOS *nmenu = (NativeMenuMacOS *)NativeMenu::get_singleton(); | 
					
						
							|  |  |  | 		nmenu->_menu_need_update(menu); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-07-11 11:17:35 +03:00
										 |  |  | - (void)menuDidClose:(NSMenu *)menu { | 
					
						
							| 
									
										
										
										
											2024-01-19 19:41:01 +02:00
										 |  |  | 	if (NativeMenu::get_singleton()) { | 
					
						
							|  |  |  | 		NativeMenuMacOS *nmenu = (NativeMenuMacOS *)NativeMenu::get_singleton(); | 
					
						
							|  |  |  | 		nmenu->_menu_close(menu); | 
					
						
							| 
									
										
										
										
											2023-07-11 11:17:35 +03:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | - (void)menu:(NSMenu *)menu willHighlightItem:(NSMenuItem *)item { | 
					
						
							|  |  |  | 	if (item) { | 
					
						
							|  |  |  | 		GodotMenuItem *value = [item representedObject]; | 
					
						
							| 
									
										
										
										
											2023-10-13 10:12:44 +03:00
										 |  |  | 		if (value && value->hover_callback.is_valid()) { | 
					
						
							| 
									
										
										
										
											2023-07-11 11:17:35 +03:00
										 |  |  | 			// If custom callback is set, use it. | 
					
						
							| 
									
										
										
										
											2023-10-12 08:27:40 +03:00
										 |  |  | 			Variant ret; | 
					
						
							|  |  |  | 			Callable::CallError ce; | 
					
						
							|  |  |  | 			const Variant *args[1] = { &value->meta }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			value->hover_callback.callp(args, 1, ret, ce); | 
					
						
							|  |  |  | 			if (ce.error != Callable::CallError::CALL_OK) { | 
					
						
							| 
									
										
										
										
											2023-11-11 22:59:05 +01:00
										 |  |  | 				ERR_PRINT(vformat("Failed to execute menu hover callback: %s.", Variant::get_callable_error_text(value->hover_callback, args, 1, ce))); | 
					
						
							| 
									
										
										
										
											2023-10-12 08:27:40 +03:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2023-07-11 11:17:35 +03:00
										 |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-08-31 11:11:52 +03:00
										 |  |  | - (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event target:(id *)target action:(SEL *)action { | 
					
						
							|  |  |  | 	NSString *ev_key = [[event charactersIgnoringModifiers] lowercaseString]; | 
					
						
							| 
									
										
										
										
											2023-01-20 11:31:07 +02:00
										 |  |  | 	NSUInteger ev_modifiers = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask; | 
					
						
							| 
									
										
										
										
											2022-08-31 11:11:52 +03:00
										 |  |  | 	for (int i = 0; i < [menu numberOfItems]; i++) { | 
					
						
							|  |  |  | 		const NSMenuItem *menu_item = [menu itemAtIndex:i]; | 
					
						
							|  |  |  | 		if ([menu_item isEnabled] && [[menu_item keyEquivalent] compare:ev_key] == NSOrderedSame) { | 
					
						
							|  |  |  | 			NSUInteger item_modifiers = [menu_item keyEquivalentModifierMask]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if (ev_modifiers == item_modifiers) { | 
					
						
							|  |  |  | 				GodotMenuItem *value = [menu_item representedObject]; | 
					
						
							| 
									
										
										
										
											2023-10-13 10:12:44 +03:00
										 |  |  | 				if (value) { | 
					
						
							|  |  |  | 					if (value->key_callback.is_valid()) { | 
					
						
							|  |  |  | 						// If custom callback is set, use it. | 
					
						
							| 
									
										
										
										
											2023-10-12 08:27:40 +03:00
										 |  |  | 						Variant ret; | 
					
						
							|  |  |  | 						Callable::CallError ce; | 
					
						
							|  |  |  | 						const Variant *args[1] = { &value->meta }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 						value->key_callback.callp(args, 1, ret, ce); | 
					
						
							|  |  |  | 						if (ce.error != Callable::CallError::CALL_OK) { | 
					
						
							| 
									
										
										
										
											2023-11-11 22:59:05 +01:00
										 |  |  | 							ERR_PRINT(vformat("Failed to execute menu key callback: %s.", Variant::get_callable_error_text(value->key_callback, args, 1, ce))); | 
					
						
							| 
									
										
										
										
											2023-10-12 08:27:40 +03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2023-10-13 10:12:44 +03:00
										 |  |  | 					} else { | 
					
						
							|  |  |  | 						// Otherwise redirect event to the engine. | 
					
						
							|  |  |  | 						if (DisplayServer::get_singleton()) { | 
					
						
							| 
									
										
										
										
											2024-10-01 08:30:30 +03:00
										 |  |  | 							if ([[NSApplication sharedApplication] keyWindow].sheet) { | 
					
						
							|  |  |  | 								[[[[NSApplication sharedApplication] keyWindow] sheetParent] sendEvent:event]; | 
					
						
							|  |  |  | 							} else { | 
					
						
							|  |  |  | 								[[[NSApplication sharedApplication] keyWindow] sendEvent:event]; | 
					
						
							|  |  |  | 							} | 
					
						
							| 
									
										
										
										
											2023-10-13 10:12:44 +03:00
										 |  |  | 						} | 
					
						
							| 
									
										
										
										
											2022-08-31 11:11:52 +03:00
										 |  |  | 					} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-13 10:12:44 +03:00
										 |  |  | 					// Suppress default menu action. | 
					
						
							|  |  |  | 					*target = self; | 
					
						
							|  |  |  | 					*action = @selector(doNothing:); | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2022-08-31 11:11:52 +03:00
										 |  |  | 				return YES; | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return NO; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | @end |