X-Git-Url: https://git.pterodactylus.net/?a=blobdiff_plain;f=synfig-osx%2Flauncher%2FX11Controller.m;fp=synfig-osx%2Flauncher%2FX11Controller.m;h=c1038044947c89b6547b761b7e6336be8762c85a;hb=a095981e18cc37a8ecc7cd237cc22b9c10329264;hp=0000000000000000000000000000000000000000;hpb=9459638ad6797b8139f1e9f0715c96076dbf0890;p=synfig.git diff --git a/synfig-osx/launcher/X11Controller.m b/synfig-osx/launcher/X11Controller.m new file mode 100644 index 0000000..c103804 --- /dev/null +++ b/synfig-osx/launcher/X11Controller.m @@ -0,0 +1,690 @@ +/* X11Controller.m -- connect the IB ui, also the NSApp delegate + $Id: X11Controller.m,v 1.36 2003/07/24 17:52:29 jharper Exp $ + + Copyright (c) 2002 Apple Computer, Inc. All rights reserved. + + 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 ABOVE LISTED COPYRIGHT + HOLDER(S) 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. + + Except as contained in this notice, the name(s) of the above + copyright holders shall not be used in advertising or otherwise to + promote the sale, use or other dealings in this Software without + prior written authorization. */ +#define __DARWIN__ + +#import "X11Controller.h" +#import "X11Application.h" +#import + + +/* ouch! */ +#define BOOL X_BOOL +# include "Xproto.h" +#define WindowPtr X_WindowPtr +#define Cursor X_Cursor +# include "quartz.h" +# define _APPLEWM_SERVER_ +# include "applewm.h" +# include "X.h" +#undef Cursor +#undef WindowPtr +#undef BOOL + +#include +#include + +#define TRACE() fprintf (stderr, "%s\n", __FUNCTION__) + +@implementation X11Controller + +- (void) awakeFromNib +{ + X11Application *xapp = NSApp; + NSArray *array; + + /* Point X11Application at ourself. */ + [xapp set_controller:self]; +#if 0 + array = [xapp prefs_get_array:@PREFS_APPSMENU]; + if (array != nil) + { + int count; + + /* convert from [TITLE1 COMMAND1 TITLE2 COMMAND2 ...] + to [[TITLE1 COMMAND1] [TITLE2 COMMAND2] ...] format. */ + + count = [array count]; + if (count > 0 + && ![[array objectAtIndex:0] isKindOfClass:[NSArray class]]) + { + int i; + NSMutableArray *copy, *sub; + + copy = [NSMutableArray arrayWithCapacity:(count / 2)]; + + for (i = 0; i < count / 2; i++) + { + sub = [[NSMutableArray alloc] initWithCapacity:3]; + [sub addObject:[array objectAtIndex:i*2]]; + [sub addObject:[array objectAtIndex:i*2+1]]; + [sub addObject:@""]; + [copy addObject:sub]; + [sub release]; + } + + array = copy; + } + + [self set_apps_menu:array]; + } + #endif +} + +- (void) item_selected:sender +{ + [NSApp activateIgnoringOtherApps:YES]; + + QuartzMessageMainThread (kXquartzControllerNotify, 2, + AppleWMWindowMenuItem, [sender tag]); +} + +- (void) remove_window_menu +{ + NSMenu *menu; + int first, count, i; + + /* Work backwards so we don't mess up the indices */ + menu = [window_separator menu]; + first = [menu indexOfItem:window_separator] + 1; + count = [menu numberOfItems]; + for (i = count - 1; i >= first; i--) + [menu removeItemAtIndex:i]; + + menu = [dock_window_separator menu]; + count = [menu indexOfItem:dock_window_separator]; + for (i = 0; i < count; i++) + [dock_menu removeItemAtIndex:0]; +} + +- (void) install_window_menu:(NSArray *)list +{ + NSMenu *menu; + NSMenuItem *item; + int first, count, i; + + menu = [window_separator menu]; + first = [menu indexOfItem:window_separator] + 1; + count = [list count]; + + for (i = 0; i < count; i++) + { + NSString *name, *shortcut; + + name = [[list objectAtIndex:i] objectAtIndex:0]; + shortcut = [[list objectAtIndex:i] objectAtIndex:1]; + + item = (NSMenuItem *) [menu addItemWithTitle:name action:@selector + (item_selected:) keyEquivalent:shortcut]; + [item setTarget:self]; + [item setTag:i]; + [item setEnabled:YES]; + + item = (NSMenuItem *) [dock_menu insertItemWithTitle:name + action:@selector + (item_selected:) keyEquivalent:shortcut + atIndex:i]; + [item setTarget:self]; + [item setTag:i]; + [item setEnabled:YES]; + } + + if (checked_window_item >= 0 && checked_window_item < count) + { + item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item]; + [item setState:NSOnState]; + item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item]; + [item setState:NSOnState]; + } +} + +- (void) remove_apps_menu +{ + NSMenu *menu; + NSMenuItem *item; + int i; + + if (apps == nil || apps_separator == nil) + return; + + menu = [apps_separator menu]; + + if (menu != nil) + { + for (i = [menu numberOfItems] - 1; i >= 0; i--) + { + item = (NSMenuItem *) [menu itemAtIndex:i]; + if ([item tag] != 0) + [menu removeItemAtIndex:i]; + } + } + + if (dock_apps_menu != nil) + { + for (i = [dock_apps_menu numberOfItems] - 1; i >= 0; i--) + { + item = (NSMenuItem *) [dock_apps_menu itemAtIndex:i]; + if ([item tag] != 0) + [dock_apps_menu removeItemAtIndex:i]; + } + } + + [apps release]; + apps = nil; +} + +- (void) prepend_apps_item:(NSArray *)list index:(int)i menu:(NSMenu *)menu +{ + NSString *title, *shortcut = @""; + NSArray *group; + NSMenuItem *item; + + group = [list objectAtIndex:i]; + title = [group objectAtIndex:0]; + if ([group count] >= 3) + shortcut = [group objectAtIndex:2]; + + if ([title length] != 0) + { + item = (NSMenuItem *) [menu insertItemWithTitle:title + action:@selector (app_selected:) + keyEquivalent:shortcut atIndex:0]; + [item setTarget:self]; + [item setEnabled:YES]; + } + else + { + item = (NSMenuItem *) [NSMenuItem separatorItem]; + [menu insertItem:item atIndex:0]; + } + + [item setTag:i+1]; /* can't be zero, so add one */ +} + +- (void) install_apps_menu:(NSArray *)list +{ + NSMenu *menu; + int i, count; + + count = [list count]; + + if (count == 0 || apps_separator == nil) + return; + + menu = [apps_separator menu]; + + for (i = count - 1; i >= 0; i--) + { + if (menu != nil) + [self prepend_apps_item:list index:i menu:menu]; + if (dock_apps_menu != nil) + [self prepend_apps_item:list index:i menu:dock_apps_menu]; + } + + apps = [list retain]; +} + +- (void) set_window_menu:(NSArray *)list +{ + [self remove_window_menu]; + [self install_window_menu:list]; + + QuartzMessageMainThread (kXquartzControllerNotify, 1, + AppleWMWindowMenuNotify); +} + +- (void) set_window_menu_check:(NSNumber *)nn +{ + NSMenu *menu; + NSMenuItem *item; + int first, count; + int n = [nn intValue]; + + menu = [window_separator menu]; + first = [menu indexOfItem:window_separator] + 1; + count = [menu numberOfItems] - first; + + if (checked_window_item >= 0 && checked_window_item < count) + { + item = (NSMenuItem *) [menu itemAtIndex:first + checked_window_item]; + [item setState:NSOffState]; + item = (NSMenuItem *) [dock_menu itemAtIndex:checked_window_item]; + [item setState:NSOffState]; + } + if (n >= 0 && n < count) + { + item = (NSMenuItem *) [menu itemAtIndex:first + n]; + [item setState:NSOnState]; + item = (NSMenuItem *) [dock_menu itemAtIndex:n]; + [item setState:NSOnState]; + } + checked_window_item = n; +} + +- (void) set_apps_menu:(NSArray *)list +{ + [self remove_apps_menu]; + [self install_apps_menu:list]; +} + +- (void) launch_client:(NSString *)command +{ + QuartzRunClient ([command cString]); +} + +- (void) app_selected:sender +{ + int tag; + NSString *item; + + tag = [sender tag] - 1; + if (apps == nil || tag < 0 || tag >= [apps count]) + return; + + item = [[apps objectAtIndex:tag] objectAtIndex:1]; + + [self launch_client:item]; +} + +- (IBAction) apps_table_show:sender +{ + NSArray *columns; + + if (table_apps == nil) + { + table_apps = [[NSMutableArray alloc] initWithCapacity:1]; + + if (apps != nil) + [table_apps addObjectsFromArray:apps]; + } + + columns = [apps_table tableColumns]; + [[columns objectAtIndex:0] setIdentifier:@"0"]; + [[columns objectAtIndex:1] setIdentifier:@"1"]; + [[columns objectAtIndex:2] setIdentifier:@"2"]; + + [apps_table setDataSource:self]; + [apps_table selectRow:0 byExtendingSelection:NO]; + + [[apps_table window] makeKeyAndOrderFront:sender]; +} + +- (IBAction) apps_table_cancel:sender +{ + [[apps_table window] orderOut:sender]; + + [table_apps release]; + table_apps = nil; +} + +- (IBAction) apps_table_done:sender +{ + [apps_table deselectAll:sender]; /* flush edits? */ + + [self remove_apps_menu]; + [self install_apps_menu:table_apps]; + + [NSApp prefs_set_array:@PREFS_APPSMENU value:table_apps]; + [NSApp prefs_synchronize]; + + [[apps_table window] orderOut:sender]; + + [table_apps release]; + table_apps = nil; +} + +- (IBAction) apps_table_new:sender +{ + NSMutableArray *item; + + int row = [apps_table selectedRow], i; + + if (row < 0) + row = 0; + else + row = row + 1; + + i = row; + if (i > [table_apps count]) + return; /* avoid exceptions */ + + item = [[NSMutableArray alloc] initWithCapacity:3]; + [item addObject:@""]; + [item addObject:@""]; + [item addObject:@""]; + + [table_apps insertObject:item atIndex:i]; + [item release]; + + [apps_table noteNumberOfRowsChanged]; + [apps_table selectRow:row byExtendingSelection:NO]; +} + +- (IBAction) apps_table_duplicate:sender +{ + int row = [apps_table selectedRow], i; + NSObject *a; + + if (row < 0) + { + [self apps_table_new:sender]; + return; + } + + i = row; + if (i > [table_apps count] - 1) + return; /* avoid exceptions */ + + a = [table_apps objectAtIndex:i]; + [table_apps insertObject:[a copy] atIndex:i]; + + [apps_table noteNumberOfRowsChanged]; + [apps_table selectRow:row+1 byExtendingSelection:NO]; +} + +- (IBAction) apps_table_delete:sender +{ + int row = [apps_table selectedRow]; + + if (row >= 0) + { + int i = row; + + if (i > [table_apps count] - 1) + return; /* avoid exceptions */ + + [table_apps removeObjectAtIndex:i]; + } + + [apps_table noteNumberOfRowsChanged]; +} + +- (int) numberOfRowsInTableView:(NSTableView *)tableView +{ + if (table_apps == nil) + return 0; + + return [table_apps count]; +} + +- (id) tableView:(NSTableView *)tableView + objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + NSArray *item; + int col; + + if (table_apps == nil) + return nil; + + col = [[tableColumn identifier] intValue]; + + item = [table_apps objectAtIndex:row]; + if ([item count] > col) + return [item objectAtIndex:col]; + else + return @""; +} + +- (void) tableView:(NSTableView *)tableView setObjectValue:(id)object + forTableColumn:(NSTableColumn *)tableColumn row:(int)row +{ + NSMutableArray *item; + int col; + + if (table_apps == nil) + return; + + col = [[tableColumn identifier] intValue]; + + item = [table_apps objectAtIndex:row]; + [item replaceObjectAtIndex:col withObject:object]; +} + +- (void) hide_window:sender +{ + if ([X11App x_active]) + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMHideWindow); + else + NSBeep (); /* FIXME: something here */ +} + +- (IBAction)bring_to_front:sender +{ + QuartzMessageMainThread (kXquartzControllerNotify, 1, + AppleWMBringAllToFront); +} + +- (IBAction)close_window:sender +{ + if ([X11App x_active]) + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMCloseWindow); + else + [[NSApp keyWindow] performClose:sender]; +} + +- (IBAction)minimize_window:sender +{ + if ([X11App x_active]) + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMMinimizeWindow); + else + [[NSApp keyWindow] performMiniaturize:sender]; +} + +- (IBAction)zoom_window:sender +{ + if ([X11App x_active]) + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMZoomWindow); + else + [[NSApp keyWindow] performZoom:sender]; +} + +- (IBAction) next_window:sender +{ + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMNextWindow); +} + +- (IBAction) previous_window:sender +{ + QuartzMessageMainThread (kXquartzControllerNotify, + 1, AppleWMPreviousWindow); +} + +- (IBAction) enable_fullscreen_changed:sender +{ + int value = ![enable_fullscreen intValue]; + + QuartzMessageMainThread (kXquartzSetRootless, 1, value); + + [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:value]; + [NSApp prefs_synchronize]; +} + +- (IBAction) toggle_fullscreen:sender +{ + QuartzMessageMainThread (kXquartzToggleFullscreen, 0); +} + +- (void) set_can_quit:(BOOL)state +{ + can_quit = state; +} + +- (IBAction)prefs_changed:sender +{ + darwinFakeButtons = [fake_buttons intValue]; + quartzUseSysBeep = [use_sysbeep intValue]; + X11EnableKeyEquivalents = [enable_keyequivs intValue]; + darwinSyncKeymap = [sync_keymap intValue]; + + /* after adding prefs here, also add to [X11Application read_defaults] + and below */ + + [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons]; + [NSApp prefs_set_boolean:@PREFS_SYSBEEP value:quartzUseSysBeep]; + [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:X11EnableKeyEquivalents]; + [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap]; + [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]]; + [NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]]; + [NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]]; + + [NSApp prefs_synchronize]; +} + +- (IBAction) prefs_show:sender +{ + [fake_buttons setIntValue:darwinFakeButtons]; + [use_sysbeep setIntValue:quartzUseSysBeep]; + [enable_keyequivs setIntValue:X11EnableKeyEquivalents]; + [sync_keymap setIntValue:darwinSyncKeymap]; + [sync_keymap setEnabled:darwinKeymapFile == NULL]; + + [enable_auth setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_AUTH default:NO]]; + [enable_tcp setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_TCP default:NO]]; + [depth selectItemAtIndex:[depth indexOfItemWithTag:[NSApp prefs_get_integer:@PREFS_DEPTH default:-1]]]; + + [enable_fullscreen setIntValue:!quartzEnableRootless]; + + [prefs_panel makeKeyAndOrderFront:sender]; +} + +- (IBAction) quit:sender +{ + QuartzMessageMainThread (kXdarwinQuit, 0); +} + +- (IBAction) x11_help:sender +{ + AHLookupAnchor (CFSTR ("Mac Help"), CFSTR ("mchlp2276")); +} + +- (BOOL) validateMenuItem:(NSMenuItem *)item +{ + NSMenu *menu = [item menu]; + + if (item == toggle_fullscreen_item) + { + return !quartzEnableRootless; + } + else if (menu == [window_separator menu] || menu == dock_menu + || (menu == [x11_about_item menu] && [item tag] == 42)) + { + return (AppleWMSelectedEvents () & AppleWMControllerNotifyMask) != 0; + } + else + { + return TRUE; + } +} + +- (void) applicationDidHide:(NSNotification *)notify +{ + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMHideAll); +} + +- (void) applicationDidUnhide:(NSNotification *)notify +{ + QuartzMessageMainThread (kXquartzControllerNotify, 1, AppleWMShowAll); +} + +- (NSApplicationTerminateReply) applicationShouldTerminate:sender +{ + NSString *msg; + + if (can_quit || [X11App prefs_get_boolean:@PREFS_NO_QUIT_ALERT default:NO]) + { + return NSTerminateNow; + } + + /* Make sure we're frontmost. */ + [NSApp activateIgnoringOtherApps:YES]; + + msg = NSLocalizedString (@"Are you sure you want to quit X11?\n\n\ +If you quit X11, any X11 applications you are running will stop immediately \ +and you will lose any changes you have not saved.", @""); + + /* FIXME: safe to run the alert in here? Or should we return Later + and then run the alert on a timer? It seems to work here, so.. */ + + return (NSRunAlertPanel (nil, msg, NSLocalizedString (@"Quit", @""), + NSLocalizedString (@"Cancel", @""), nil) + == NSAlertDefaultReturn) ? NSTerminateNow : NSTerminateCancel; +} + +- (void) applicationWillTerminate:(NSNotification *)aNotification +{ + [X11App prefs_synchronize]; + + /* shutdown the X server, it will exit () for us. */ + QuartzMessageMainThread (kXdarwinQuit, 0); + + /* In case it doesn't, exit anyway after a while. */ + while (sleep (10) != 0) ; + exit (1); +} + +- (void) server_ready +{ + x_list *node; + + finished_launching = YES; + + for (node = pending_apps; node != NULL; node = node->next) + { + NSString *filename = node->data; + QuartzRunClient ([filename UTF8String]); + [filename release]; + } + + x_list_free (pending_apps); + pending_apps = NULL; +} + +- (BOOL) application:(NSApplication *)app openFile:(NSString *)filename +{ +#if 0 + const char *name = [filename UTF8String]; + + if (finished_launching) + QuartzRunClient (name); + else if (name[0] != ':') /* ignore display names */ + pending_apps = x_list_prepend (pending_apps, [filename retain]); + + /* FIXME: report failures. */ + return YES; +#endif + return NO; +} + +@end + +void X11ControllerMain (int argc, const char *argv[], + void (*server_thread) (void *), void *server_arg) +{ + X11ApplicationMain (argc, argv, server_thread, server_arg); +}