20 #include <objc/objc-runtime.h>
21 #include <CoreGraphics/CGBase.h>
22 #include <CoreGraphics/CGGeometry.h>
26 static id auto_release_pool;
27 static id application;
29 static const unsigned long NSFileHandlingPanelOKButton = 1;
30 static const unsigned long NSFileHandlingPanelCancelButton = 0;
40 static void _xemumacgui_menu_action_handler (
id self,
SEL selector,
id sender )
42 id menu_obj = ((
id (*) (
id, SEL)) objc_msgSend)(sender, sel_registerName(
"representedObject"));
43 const struct menu_st* menu_item = (
const struct menu_st*) ((
id (*) (
id, SEL)) objc_msgSend)(menu_obj, sel_registerName(
"pointerValue"));
45 DEBUGPRINT(
"GUI: menu point \"%s\" has been activated." NL, menu_item->
name);
48 DEBUGPRINT(
"GUI: menu point is NOT activated in action handler! menu_item=%p menu_item->type=%d" NL, menu_item, menu_item ? menu_item->
type : -1 );
54 static id _xemumacgui_r_menu_builder (
const struct menu_st desc[],
const char *parent_name )
56 id menu_item, menu_state;
57 id ui_menu = ((
id (*) (Class, SEL)) objc_msgSend)(objc_getClass(
"NSMenu"), sel_registerName(
"new"));
58 ((void (*) (
id, SEL)) objc_msgSend)(ui_menu, sel_registerName(
"autorelease"));
59 for (
int a = 0; desc[a].
name; a++) {
70 DEBUGPRINT(
"GUI: invalid menu entry found, skipping it (item #%d of menu \"%s\")" NL, a, parent_name);
81 menu_item = ((
id (*) (Class, SEL)) objc_msgSend)(objc_getClass(
"NSMenuItem"), sel_registerName(
"separatorItem"));
83 menu_item = ((
id (*) (Class, SEL)) objc_msgSend)(objc_getClass(
"NSMenuItem"), sel_registerName(
"alloc"));
84 ((void (*) (
id, SEL)) objc_msgSend)(menu_item, sel_registerName(
"autorelease"));
85 id str_name = ((
id (*) (Class, SEL,
const char*)) objc_msgSend)(
86 objc_getClass(
"NSString"),
87 sel_registerName(
"stringWithUTF8String:"),
90 id str_key = ((
id (*) (Class, SEL,
const char*)) objc_msgSend)(
91 objc_getClass(
"NSString"),
92 sel_registerName(
"stringWithUTF8String:"),
95 ((void (*) (
id, SEL,
id, SEL,
id))objc_msgSend)(
97 sel_registerName(
"initWithTitle:action:keyEquivalent:"),
99 sel_registerName(
"menuActionHandler"),
102 ((void (*) (
id, SEL, BOOL)) objc_msgSend)(menu_item, sel_registerName(
"setEnabled:"), YES);
103 id menu_object = ((
id (*) (Class, SEL,
id)) objc_msgSend) (objc_getClass(
"NSValue"), sel_registerName(
"valueWithPointer:"),(
id) &desc[a]);
104 ((void (*) (
id, SEL,
id))objc_msgSend)(menu_item, sel_registerName(
"setRepresentedObject:"), menu_object);
107 ((
id (*) (
id, SEL, int)) objc_msgSend)(menu_item, sel_registerName(
"setState:"), 1);
109 ((void (*) (
id, SEL,
id))objc_msgSend)(ui_menu, sel_registerName(
"addItem:"), menu_item);
112 id sub_menu = _xemumacgui_r_menu_builder(desc[a].
user_data, desc[a].
name);
113 ((void (*) (
id, SEL,
id,
id))objc_msgSend)(ui_menu, sel_registerName(
"setSubmenu:forItem:"), sub_menu, menu_item);
120 static int xemuosxgui_init (
void )
123 auto_release_pool = ((
id (*) (Class, SEL)) objc_msgSend)(objc_getClass(
"NSAutoreleasePool"), sel_registerName(
"new"));
124 application = ((
id (*) (Class, SEL)) objc_msgSend)(objc_getClass(
"NSApplication"), sel_registerName(
"sharedApplication"));
125 id app_delegate = ((
id (*) (
id, SEL)) objc_msgSend)(application, sel_registerName(
"delegate"));
126 Class xemu_ui_delegate_class = ((Class (*) (
id, SEL)) objc_msgSend)(app_delegate, sel_registerName(
"class"));
127 class_addMethod(xemu_ui_delegate_class, sel_registerName(
"menuActionHandler"), (IMP)_xemumacgui_menu_action_handler,
"v@:@");
132 static int xemuosxgui_popup (
const struct menu_st desc[] )
135 if ( ! (((
id(*)(
id,
SEL))objc_msgSend) (application, sel_registerName(
"mainWindow")))) {
136 ((void(*)(
id,SEL,BOOL))objc_msgSend) (application, sel_registerName(
"activateIgnoringOtherApps:"), YES);
144 NSPoint mouse_location = ((
NSPoint (*) (Class, SEL)) objc_msgSend)
145 (objc_getClass(
"NSEvent"), sel_registerName(
"mouseLocation"));
147 (ui_menu, sel_registerName(
"popUpMenuPositioningItem:atLocation:inView:"), nil, mouse_location, nil);
151 static int xemuosxgui_file_selector (
int dialog_mode,
const char *dialog_title,
char *default_dir,
char *selected,
int path_max_size )
153 char panel_type[12] = { 0 };
154 char open_selector[10] = { 0 };
155 switch ( dialog_mode & 3 ) {
157 strncpy(panel_type,
"NSOpenPanel",
sizeof(panel_type));
158 strncpy(open_selector,
"openPanel",
sizeof(open_selector));
161 strncpy(panel_type,
"NSSavePanel",
sizeof(panel_type));
162 strncpy(open_selector,
"savePanel",
sizeof(open_selector));
165 FATAL(
"Invalid mode for UI selector: %d", dialog_mode & 3);
169 id file_panel = ((
id (*) (Class, SEL)) objc_msgSend)(objc_getClass(panel_type), sel_registerName(open_selector));
170 ((void (*) (
id, SEL)) objc_msgSend)(file_panel, sel_registerName(
"autorelease"));
171 id main_window = ((
id (*) (
id, SEL)) objc_msgSend)(application, sel_registerName(
"mainWindow"));
173 ((void (*) (
id, SEL, BOOL)) objc_msgSend)(file_panel, sel_registerName(
"setCanChooseDirectories:"), NO);
174 ((void (*) (
id, SEL, BOOL)) objc_msgSend)(file_panel, sel_registerName(
"setAllowsMultipleSelection:"), NO);
176 id dialog_title_str = ((
id (*) (Class, SEL,
const char*)) objc_msgSend)
177 (objc_getClass(
"NSString"), sel_registerName(
"stringWithUTF8String:"), dialog_title);
178 ((void (*) (
id, SEL,
id)) objc_msgSend)(file_panel, sel_registerName(
"setMessage:"), dialog_title_str);
180 id default_dir_str = ((
id (*) (Class, SEL,
const char*)) objc_msgSend)
181 (objc_getClass(
"NSString"), sel_registerName(
"stringWithUTF8String:"), default_dir);
182 id dir_url = ((
id (*) (Class, SEL,
id)) objc_msgSend)(objc_getClass(
"NSURL"), sel_registerName(
"fileURLWithPath:"), default_dir_str);
183 ((void (*) (
id, SEL,
id)) objc_msgSend) (file_panel, sel_registerName(
"directoryURL"), dir_url);
185 id panel_result = ((
id (*) (
id, SEL)) objc_msgSend)(file_panel, sel_registerName(
"runModal"));
186 ((void (*) (
id, SEL)) objc_msgSend)(main_window, sel_registerName(
"makeKeyWindow"));
187 if ((
unsigned long)panel_result == NSFileHandlingPanelOKButton) {
191 id url_array = ((
id (*) (
id, SEL)) objc_msgSend)(file_panel, sel_registerName(
"URLs"));
192 filename_url = ((
id (*) (
id, SEL, int)) objc_msgSend)(url_array, sel_registerName(
"objectAtIndex:"), 0);
194 filename_url = ((
id (*) (
id, SEL)) objc_msgSend)(file_panel, sel_registerName(
"URL"));
196 const char* filename = (
const char*)((
id (*) (
id, SEL)) objc_msgSend)(filename_url, sel_registerName(
"fileSystemRepresentation"));
197 strcpy(selected, filename);
198 store_dir_from_file_selection(default_dir, filename, dialog_mode);
207 .description =
"MacOS native API Xemu UI implementation",
208 .init = xemuosxgui_init,
211 .file_selector = xemuosxgui_file_selector,
212 .popup = xemuosxgui_popup,