1 /* X11Controller.m -- connect the IB ui, also the NSApp delegate
3 * Copyright (c) 2002-2012 Apple Inc. All rights reserved.
5 * Permission is hereby granted, free of charge, to any person
6 * obtaining a copy of this software and associated documentation files
7 * (the "Software"), to deal in the Software without restriction,
8 * including without limitation the rights to use, copy, modify, merge,
9 * publish, distribute, sublicense, and/or sell copies of the Software,
10 * and to permit persons to whom the Software is furnished to do so,
11 * subject to the following conditions:
13 * The above copyright notice and this permission notice shall be
14 * included in all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19 * NONINFRINGEMENT. IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT
20 * HOLDER(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
21 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
23 * DEALINGS IN THE SOFTWARE.
25 * Except as contained in this notice, the name(s) of the above
26 * copyright holders shall not be used in advertising or otherwise to
27 * promote the sale, use or other dealings in this Software without
28 * prior written authorization.
31 #include "sanitizedCarbon.h"
32 #include <AvailabilityMacros.h>
34 #ifdef HAVE_DIX_CONFIG_H
35 #include <dix-config.h>
38 #include "quartzCommon.h"
40 #import "X11Controller.h"
41 #import "X11Application.h"
45 #include "darwinEvents.h"
47 #include "quartzKeyboard.h"
48 #include <X11/extensions/applewmconst.h>
49 #include "applewmExt.h"
54 #include <sys/types.h>
59 extern aslclient aslc;
60 extern char *bundle_id_prefix;
62 @implementation X11Controller
66 X11Application *xapp = NSApp;
69 /* Point X11Application at ourself. */
70 [xapp set_controller:self];
72 array = [xapp prefs_get_array:@PREFS_APPSMENU];
76 /* convert from [TITLE1 COMMAND1 TITLE2 COMMAND2 ...]
77 to [[TITLE1 COMMAND1] [TITLE2 COMMAND2] ...] format. */
79 count = [array count];
81 && ![[array objectAtIndex:0] isKindOfClass:[NSArray class]]) {
83 NSMutableArray *copy, *sub;
85 copy = [NSMutableArray arrayWithCapacity:(count / 2)];
87 for (i = 0; i < count / 2; i++) {
88 sub = [[NSMutableArray alloc] initWithCapacity:3];
89 [sub addObject:[array objectAtIndex:i * 2]];
90 [sub addObject:[array objectAtIndex:i * 2 + 1]];
99 [self set_apps_menu:array];
102 [[NSNotificationCenter defaultCenter]
104 selector: @selector(apps_table_done:)
105 name: NSWindowWillCloseNotification
106 object: [apps_table window]];
108 // Setup data about our Windows menu
109 if (window_separator) {
110 [[window_separator menu] removeItem:window_separator];
111 window_separator = nil;
114 windows_menu_start = [[X11App windowsMenu] numberOfItems];
117 - (void) item_selected:sender
119 [NSApp activateIgnoringOtherApps:YES];
121 DarwinSendDDXEvent(kXquartzControllerNotify, 2,
122 AppleWMWindowMenuItem, [sender tag]);
125 - (void) remove_window_menu
130 /* Work backwards so we don't mess up the indices */
131 menu = [X11App windowsMenu];
132 count = [menu numberOfItems];
133 for (i = count - 1; i >= windows_menu_start; i--)
134 [menu removeItemAtIndex:i];
136 count = [dock_menu indexOfItem:dock_window_separator];
137 for (i = 0; i < count; i++)
138 [dock_menu removeItemAtIndex:0];
141 - (void) install_window_menu:(NSArray *)list
147 menu = [X11App windowsMenu];
148 first = windows_menu_start + 1;
149 count = [list count];
153 [menu addItem:[NSMenuItem separatorItem]];
156 for (i = 0; i < count; i++) {
157 NSString *name, *shortcut;
159 name = [[list objectAtIndex:i] objectAtIndex:0];
160 shortcut = [[list objectAtIndex:i] objectAtIndex:1];
162 if (windowItemModMask == 0 || windowItemModMask == -1)
166 (NSMenuItem *)[menu addItemWithTitle:name action:
168 (item_selected:) keyEquivalent:shortcut];
169 [item setKeyEquivalentModifierMask:(NSUInteger)windowItemModMask];
170 [item setTarget:self];
172 [item setEnabled:YES];
174 item = (NSMenuItem *)[dock_menu insertItemWithTitle:name
176 (item_selected:) keyEquivalent:shortcut
178 [item setKeyEquivalentModifierMask:(NSUInteger)windowItemModMask];
179 [item setTarget:self];
181 [item setEnabled:YES];
184 if (checked_window_item >= 0 && checked_window_item < count) {
185 item = (NSMenuItem *)[menu itemAtIndex:first + checked_window_item];
186 [item setState:NSOnState];
187 item = (NSMenuItem *)[dock_menu itemAtIndex:checked_window_item];
188 [item setState:NSOnState];
192 - (void) remove_apps_menu
198 if (apps == nil || apps_separator == nil) return;
200 menu = [apps_separator menu];
203 for (i = [menu numberOfItems] - 1; i >= 0; i--) {
204 item = (NSMenuItem *)[menu itemAtIndex:i];
206 [menu removeItemAtIndex:i];
210 if (dock_apps_menu != nil) {
211 for (i = [dock_apps_menu numberOfItems] - 1; i >= 0; i--) {
212 item = (NSMenuItem *)[dock_apps_menu itemAtIndex:i];
214 [dock_apps_menu removeItemAtIndex:i];
222 - (void) prepend_apps_item:(NSArray *)list index:(int)i menu:(NSMenu *)menu
224 NSString *title, *shortcut = @"";
228 group = [list objectAtIndex:i];
229 title = [group objectAtIndex:0];
230 if ([group count] >= 3)
231 shortcut = [group objectAtIndex:2];
233 if ([title length] != 0) {
234 item = (NSMenuItem *)[menu insertItemWithTitle:title
237 keyEquivalent:shortcut atIndex:0];
238 [item setTarget:self];
239 [item setEnabled:YES];
242 item = (NSMenuItem *)[NSMenuItem separatorItem];
243 [menu insertItem:item atIndex:0];
246 [item setTag:i + 1]; /* can't be zero, so add one */
249 - (void) install_apps_menu:(NSArray *)list
254 count = [list count];
256 if (count == 0 || apps_separator == nil) return;
258 menu = [apps_separator menu];
260 for (i = count - 1; i >= 0; i--) {
262 [self prepend_apps_item:list index:i menu:menu];
263 if (dock_apps_menu != nil)
264 [self prepend_apps_item:list index:i menu:dock_apps_menu];
267 apps = [list retain];
270 - (void) set_window_menu:(NSArray *)list
272 [self remove_window_menu];
273 [self install_window_menu:list];
275 DarwinSendDDXEvent(kXquartzControllerNotify, 1,
276 AppleWMWindowMenuNotify);
279 - (void) set_window_menu_check:(NSNumber *)nn
284 int n = [nn intValue];
286 menu = [X11App windowsMenu];
287 first = windows_menu_start + 1;
288 count = [menu numberOfItems] - first;
290 if (checked_window_item >= 0 && checked_window_item < count) {
291 item = (NSMenuItem *)[menu itemAtIndex:first + checked_window_item];
292 [item setState:NSOffState];
293 item = (NSMenuItem *)[dock_menu itemAtIndex:checked_window_item];
294 [item setState:NSOffState];
296 if (n >= 0 && n < count) {
297 item = (NSMenuItem *)[menu itemAtIndex:first + n];
298 [item setState:NSOnState];
299 item = (NSMenuItem *)[dock_menu itemAtIndex:n];
300 [item setState:NSOnState];
302 checked_window_item = n;
305 - (void) set_apps_menu:(NSArray *)list
307 [self remove_apps_menu];
308 [self install_apps_menu:list];
311 #ifdef XQUARTZ_SPARKLE
312 - (void) setup_sparkle
314 if (check_for_updates_item)
315 return; // already did it...
317 NSMenu *menu = [x11_about_item menu];
319 check_for_updates_item =
320 [menu insertItemWithTitle:NSLocalizedString(
321 @"Check for X11 Updates...",
322 @"Check for X11 Updates...")
327 [check_for_updates_item setTarget:[SUUpdater sharedUpdater]];
328 [check_for_updates_item setEnabled:YES];
330 // Set X11Controller as the delegate for the updater.
331 [[SUUpdater sharedUpdater] setDelegate:self];
334 // Sent immediately before installing the specified update.
335 - (void)updater:(SUUpdater *)updater willInstallUpdate:(SUAppcastItem *)
338 //[self set_can_quit:YES];
343 - (void) launch_client:(NSString *)filename
345 int child1, child2 = 0;
347 const char *newargv[4];
350 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
355 newargv[0] = [X11App prefs_get_string:@PREFS_LOGIN_SHELL default:"/bin/sh"];
357 newargv[2] = [filename UTF8String];
360 s = getenv("DISPLAY");
361 if (s == NULL || s[0] == 0) {
362 snprintf(buf, sizeof(buf), ":%s", display);
363 setenv("DISPLAY", buf, TRUE);
366 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
367 if (asl_log_descriptor) {
369 aslmsg amsg = asl_new(ASL_TYPE_MSG);
372 asprintf(&asl_sender, "%s.%s", bundle_id_prefix, newargv[2]);
374 for(s = asl_sender + strlen(bundle_id_prefix) + 1; *s; s++) {
375 if(! ((*s >= 'a' && *s <= 'z') ||
376 (*s >= 'A' && *s <= 'Z') ||
377 (*s >= '0' && *s <= '9'))) {
382 (void)asl_set(amsg, ASL_KEY_SENDER, asl_sender);
385 assert(0 == pipe(stdout_pipe));
386 fcntl(stdout_pipe[0], F_SETFD, FD_CLOEXEC);
387 fcntl(stdout_pipe[0], F_SETFL, O_NONBLOCK);
389 assert(0 == pipe(stderr_pipe));
390 fcntl(stderr_pipe[0], F_SETFD, FD_CLOEXEC);
391 fcntl(stderr_pipe[0], F_SETFL, O_NONBLOCK);
393 asl_log_descriptor(aslc, amsg, ASL_LEVEL_INFO, stdout_pipe[0], ASL_LOG_DESCRIPTOR_READ);
394 asl_log_descriptor(aslc, amsg, ASL_LEVEL_NOTICE, stderr_pipe[0], ASL_LOG_DESCRIPTOR_READ);
400 /* Do the fork-twice trick to avoid having to reap zombies */
416 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
417 if (asl_log_descriptor) {
418 /* Replace our stdout/stderr */
419 dup2(stdout_pipe[1], STDOUT_FILENO);
420 dup2(stderr_pipe[1], STDERR_FILENO);
424 /* close all open files except for standard streams */
425 max_files = sysconf(_SC_OPEN_MAX);
426 for (i = 3; i < max_files; i++)
429 /* ensure stdin is on /dev/null */
431 open("/dev/null", O_RDONLY);
433 execvp(newargv[0], (char * *const)newargv);
436 default: /* parent (child1) */
441 default: /* parent */
442 waitpid(child1, &status, 0);
445 #if MAC_OS_X_VERSION_MAX_ALLOWED >= 1080
446 if (asl_log_descriptor) {
447 /* Close the write ends of the pipe */
448 close(stdout_pipe[1]);
449 close(stderr_pipe[1]);
454 - (void) app_selected:sender
459 tag = [sender tag] - 1;
460 if (apps == nil || tag < 0 || tag >= [apps count])
463 item = [[apps objectAtIndex:tag] objectAtIndex:1];
465 [self launch_client:item];
468 - (IBAction) apps_table_show:sender
471 NSMutableArray *oldapps = nil;
473 if (table_apps != nil)
474 oldapps = table_apps;
476 table_apps = [[NSMutableArray alloc] initWithCapacity:1];
478 [table_apps addObjectsFromArray:apps];
480 columns = [apps_table tableColumns];
481 [[columns objectAtIndex:0] setIdentifier:@"0"];
482 [[columns objectAtIndex:1] setIdentifier:@"1"];
483 [[columns objectAtIndex:2] setIdentifier:@"2"];
485 [apps_table setDataSource:self];
486 [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:0]
487 byExtendingSelection:NO];
489 [[apps_table window] makeKeyAndOrderFront:sender];
490 [apps_table reloadData];
495 - (IBAction) apps_table_done:sender
497 [apps_table deselectAll:sender]; /* flush edits? */
499 [self remove_apps_menu];
500 [self install_apps_menu:table_apps];
502 [NSApp prefs_set_array:@PREFS_APPSMENU value:table_apps];
503 [NSApp prefs_synchronize];
505 [[apps_table window] orderOut:sender];
507 [table_apps release];
511 - (IBAction) apps_table_new:sender
513 NSMutableArray *item;
515 int row = [apps_table selectedRow], i;
517 if (row < 0) row = 0;
521 if (i > [table_apps count])
522 return; /* avoid exceptions */
524 [apps_table deselectAll:sender];
526 item = [[NSMutableArray alloc] initWithCapacity:3];
527 [item addObject:@""];
528 [item addObject:@""];
529 [item addObject:@""];
531 [table_apps insertObject:item atIndex:i];
534 [apps_table reloadData];
535 [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
536 byExtendingSelection:NO];
539 - (IBAction) apps_table_duplicate:sender
541 int row = [apps_table selectedRow], i;
545 [self apps_table_new:sender];
550 if (i > [table_apps count] - 1) return; /* avoid exceptions */
552 [apps_table deselectAll:sender];
554 item = [[table_apps objectAtIndex:i] mutableCopy];
555 [table_apps insertObject:item atIndex:i];
558 [apps_table reloadData];
559 [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row +
560 1] byExtendingSelection:NO];
563 - (IBAction) apps_table_delete:sender
565 int row = [apps_table selectedRow];
570 if (i > [table_apps count] - 1) return; /* avoid exceptions */
572 [apps_table deselectAll:sender];
574 [table_apps removeObjectAtIndex:i];
577 [apps_table reloadData];
579 row = MIN(row, [table_apps count] - 1);
581 [apps_table selectRowIndexes:[NSIndexSet indexSetWithIndex:row]
582 byExtendingSelection:NO];
585 - (NSInteger) numberOfRowsInTableView:(NSTableView *)tableView
587 if (table_apps == nil) return 0;
589 return [table_apps count];
592 - (id) tableView:(NSTableView *)tableView
593 objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
598 if (table_apps == nil) return nil;
600 col = [[tableColumn identifier] intValue];
602 item = [table_apps objectAtIndex:row];
603 if ([item count] > col)
604 return [item objectAtIndex:col];
609 - (void) tableView:(NSTableView *)tableView setObjectValue:(id)object
610 forTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
612 NSMutableArray *item;
615 if (table_apps == nil) return;
617 col = [[tableColumn identifier] intValue];
619 item = [table_apps objectAtIndex:row];
620 [item replaceObjectAtIndex:col withObject:object];
623 - (void) hide_window:sender
625 if ([X11App x_active])
626 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMHideWindow);
628 NSBeep(); /* FIXME: something here */
631 - (IBAction)bring_to_front:sender
633 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMBringAllToFront);
636 - (IBAction)close_window:sender
638 if ([X11App x_active])
639 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMCloseWindow);
641 [[NSApp keyWindow] performClose:sender];
644 - (IBAction)minimize_window:sender
646 if ([X11App x_active])
647 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMMinimizeWindow);
649 [[NSApp keyWindow] performMiniaturize:sender];
652 - (IBAction)zoom_window:sender
654 if ([X11App x_active])
655 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMZoomWindow);
657 [[NSApp keyWindow] performZoom:sender];
660 - (IBAction) next_window:sender
662 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMNextWindow);
665 - (IBAction) previous_window:sender
667 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMPreviousWindow);
670 - (IBAction) enable_fullscreen_changed:sender
672 XQuartzRootlessDefault = ![enable_fullscreen intValue];
674 [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault];
675 [enable_fullscreen_menu_text setTextColor:XQuartzRootlessDefault ?[
676 NSColor disabledControlTextColor] : [NSColor controlTextColor]];
678 DarwinSendDDXEvent(kXquartzSetRootless, 1, XQuartzRootlessDefault);
680 [NSApp prefs_set_boolean:@PREFS_ROOTLESS value:XQuartzRootlessDefault];
681 [NSApp prefs_synchronize];
684 - (IBAction) toggle_fullscreen:sender
686 DarwinSendDDXEvent(kXquartzToggleFullscreen, 0);
689 - (void) set_can_quit:(OSX_BOOL)state
694 - (IBAction)prefs_changed:sender
699 if (sender == fake_buttons) {
700 darwinFakeButtons = [fake_buttons intValue];
701 [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons];
703 else if (sender == enable_keyequivs) {
704 XQuartzEnableKeyEquivalents = [enable_keyequivs intValue];
705 [NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:
706 XQuartzEnableKeyEquivalents];
708 else if (sender == sync_keymap) {
709 darwinSyncKeymap = [sync_keymap intValue];
710 [NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap];
712 else if (sender == enable_fullscreen_menu) {
713 XQuartzFullscreenMenu = [enable_fullscreen_menu intValue];
714 [NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:
715 XQuartzFullscreenMenu];
717 else if (sender == option_sends_alt) {
718 BOOL prev_opt_sends_alt = XQuartzOptionSendsAlt;
720 XQuartzOptionSendsAlt = [option_sends_alt intValue];
721 [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value:
722 XQuartzOptionSendsAlt];
724 if (prev_opt_sends_alt != XQuartzOptionSendsAlt)
725 QuartsResyncKeymap(TRUE);
727 else if (sender == click_through) {
728 [NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through
731 else if (sender == focus_follows_mouse) {
732 [NSApp prefs_set_boolean:@PREFS_FFM value:[focus_follows_mouse
735 else if (sender == focus_on_new_window) {
736 [NSApp prefs_set_boolean:@PREFS_FOCUS_ON_NEW_WINDOW value:[
737 focus_on_new_window intValue]];
739 else if (sender == enable_auth) {
740 [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]
743 else if (sender == enable_tcp) {
744 [NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]];
746 else if (sender == depth) {
747 [NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]];
749 else if (sender == sync_pasteboard) {
750 BOOL pbproxy_active = [sync_pasteboard intValue];
751 [NSApp prefs_set_boolean:@PREFS_SYNC_PB value:pbproxy_active];
753 [sync_pasteboard_to_clipboard setEnabled:pbproxy_active];
754 [sync_pasteboard_to_primary setEnabled:pbproxy_active];
755 [sync_clipboard_to_pasteboard setEnabled:pbproxy_active];
756 [sync_primary_immediately setEnabled:pbproxy_active];
758 // setEnabled doesn't do this...
759 [sync_text1 setTextColor:pbproxy_active ?[NSColor controlTextColor] :
760 [NSColor disabledControlTextColor]];
761 [sync_text2 setTextColor:pbproxy_active ?[NSColor controlTextColor] :
762 [NSColor disabledControlTextColor]];
764 else if (sender == sync_pasteboard_to_clipboard) {
765 [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD value:[
766 sync_pasteboard_to_clipboard intValue]];
768 else if (sender == sync_pasteboard_to_primary) {
769 [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_PRIMARY value:[
770 sync_pasteboard_to_primary intValue]];
772 else if (sender == sync_clipboard_to_pasteboard) {
773 [NSApp prefs_set_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB value:[
774 sync_clipboard_to_pasteboard intValue]];
776 else if (sender == sync_primary_immediately) {
777 [NSApp prefs_set_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT value:[
778 sync_primary_immediately intValue]];
780 else if (sender == scroll_in_device_direction) {
781 XQuartzScrollInDeviceDirection =
782 [scroll_in_device_direction intValue];
783 [NSApp prefs_set_boolean:@PREFS_SCROLL_IN_DEV_DIRECTION value:
784 XQuartzScrollInDeviceDirection];
787 [NSApp prefs_synchronize];
789 DarwinSendDDXEvent(kXquartzReloadPreferences, 0);
792 - (IBAction) prefs_show:sender
794 BOOL pbproxy_active =
795 [NSApp prefs_get_boolean:@PREFS_SYNC_PB default:YES];
797 // Remove preferences from the GUI which are not supported
798 // TODO: Change 1117 to NSAppKitVersionNumber10_7 when it is defined
799 if (scroll_in_device_direction && NSAppKitVersionNumber < 1117) {
800 [scroll_in_device_direction removeFromSuperview];
801 scroll_in_device_direction = nil;
804 [scroll_in_device_direction setIntValue:
805 XQuartzScrollInDeviceDirection];
808 [fake_buttons setIntValue:darwinFakeButtons];
809 [enable_keyequivs setIntValue:XQuartzEnableKeyEquivalents];
810 [sync_keymap setIntValue:darwinSyncKeymap];
811 [option_sends_alt setIntValue:XQuartzOptionSendsAlt];
812 [click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH
814 [focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM
816 [focus_on_new_window setIntValue:[NSApp prefs_get_boolean:
817 @PREFS_FOCUS_ON_NEW_WINDOW default:YES]
820 [enable_auth setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_AUTH default
822 [enable_tcp setIntValue:![NSApp prefs_get_boolean:@PREFS_NO_TCP default:
825 [depth selectItemAtIndex:[depth indexOfItemWithTag:[NSApp
827 @PREFS_DEPTH default:
830 [sync_pasteboard setIntValue:pbproxy_active];
831 [sync_pasteboard_to_clipboard setIntValue:[NSApp prefs_get_boolean:
832 @PREFS_SYNC_PB_TO_CLIPBOARD
834 [sync_pasteboard_to_primary setIntValue:[NSApp prefs_get_boolean:
835 @PREFS_SYNC_PB_TO_PRIMARY
837 [sync_clipboard_to_pasteboard setIntValue:[NSApp prefs_get_boolean:
838 @PREFS_SYNC_CLIPBOARD_TO_PB
840 [sync_primary_immediately setIntValue:[NSApp prefs_get_boolean:
841 @PREFS_SYNC_PRIMARY_ON_SELECT
844 [sync_pasteboard_to_clipboard setEnabled:pbproxy_active];
845 [sync_pasteboard_to_primary setEnabled:pbproxy_active];
846 [sync_clipboard_to_pasteboard setEnabled:pbproxy_active];
847 [sync_primary_immediately setEnabled:pbproxy_active];
849 // setEnabled doesn't do this...
850 [sync_text1 setTextColor:pbproxy_active ?[NSColor controlTextColor] : [
851 NSColor disabledControlTextColor]];
852 [sync_text2 setTextColor:pbproxy_active ?[NSColor controlTextColor] : [
853 NSColor disabledControlTextColor]];
855 [enable_fullscreen setIntValue:!XQuartzRootlessDefault];
856 [enable_fullscreen_menu setIntValue:XQuartzFullscreenMenu];
857 [enable_fullscreen_menu setEnabled:!XQuartzRootlessDefault];
858 [enable_fullscreen_menu_text setTextColor:XQuartzRootlessDefault ?[
859 NSColor disabledControlTextColor] : [NSColor controlTextColor]];
861 [prefs_panel makeKeyAndOrderFront:sender];
864 - (IBAction) quit:sender
866 DarwinSendDDXEvent(kXquartzQuit, 0);
869 - (IBAction) x11_help:sender
871 #if MAC_OS_X_VERSION_MIN_REQUIRED < 1060
872 AHLookupAnchor((CFStringRef)NSLocalizedString(@"Mac Help",
876 AHLookupAnchor(CFSTR("com.apple.machelp"), CFSTR("mchlp2276"));
880 - (OSX_BOOL) validateMenuItem:(NSMenuItem *)item
882 NSMenu *menu = [item menu];
884 if (item == toggle_fullscreen_item)
885 return !XQuartzIsRootless;
886 else if (menu == [X11App windowsMenu] || menu == dock_menu
887 || (menu == [x11_about_item menu] && [item tag] == 42))
888 return (AppleWMSelectedEvents() & AppleWMControllerNotifyMask) != 0;
893 - (void) applicationDidHide:(NSNotification *)notify
895 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMHideAll);
897 /* Toggle off fullscreen mode to leave our non-default video
898 * mode and hide our guard window.
900 if (!XQuartzIsRootless && XQuartzFullscreenVisible) {
901 DarwinSendDDXEvent(kXquartzToggleFullscreen, 0);
905 - (void) applicationDidUnhide:(NSNotification *)notify
907 DarwinSendDDXEvent(kXquartzControllerNotify, 1, AppleWMShowAll);
910 - (NSApplicationTerminateReply) applicationShouldTerminate:sender
916 [X11App prefs_get_boolean:@PREFS_NO_QUIT_ALERT default:NO])
917 return NSTerminateNow;
919 /* Make sure we're frontmost. */
920 [NSApp activateIgnoringOtherApps:YES];
922 title = NSLocalizedString(@"Do you really want to quit X11?",
923 @"Dialog title when quitting");
924 msg = NSLocalizedString(
925 @"Any open X11 applications will stop immediately, and you will lose any unsaved changes.",
926 @"Dialog when quitting");
928 /* FIXME: safe to run the alert in here? Or should we return Later
929 * and then run the alert on a timer? It seems to work here, so..
932 return (NSRunAlertPanel(title, msg, NSLocalizedString(@"Quit", @""),
933 NSLocalizedString(@"Cancel", @""), nil)
934 == NSAlertDefaultReturn) ? NSTerminateNow : NSTerminateCancel;
937 - (void) applicationWillTerminate:(NSNotification *)aNotification _X_NORETURN
940 [X11App prefs_synchronize];
942 /* shutdown the X server, it will exit () for us. */
943 DarwinSendDDXEvent(kXquartzQuit, 0);
945 /* In case it doesn't, exit anyway after a while. */
947 while ((remain = usleep(remain)) > 0) ;
952 - (void) server_ready
956 finished_launching = YES;
958 for (node = pending_apps; node != NULL; node = node->next) {
959 NSString *filename = node->data;
960 [self launch_client:filename];
964 x_list_free(pending_apps);
968 - (OSX_BOOL) application:(NSApplication *)app openFile:(NSString *)filename
970 const char *name = [filename UTF8String];
972 if (finished_launching)
973 [self launch_client:filename];
974 else if (name[0] != ':') /* ignore display names */
975 pending_apps = x_list_prepend(pending_apps, [filename retain]);
977 /* FIXME: report failures. */
984 X11ControllerMain(int argc, char **argv, char **envp)
986 X11ApplicationMain(argc, argv, envp);