XQuartz: Add a defaults option to toggle Alt / Mode_switch

See option_sends_alt in Xquartz(1)

Signed-off-by: Jeremy Huddleston <jeremyhu@apple.com>
Reviewed-by: Kevin Van Vechten <kvv@apple.com>
This commit is contained in:
Jeremy Huddleston 2010-04-09 13:29:34 -07:00
parent d6f160510a
commit 840d12c7a6
9 changed files with 101 additions and 61 deletions

View File

@ -90,6 +90,7 @@ extern int quartzHasRoot, quartzEnableRootless, quartzFullscreenMenu;
#define PREFS_NO_TCP "nolisten_tcp" #define PREFS_NO_TCP "nolisten_tcp"
#define PREFS_DONE_XINIT_CHECK "done_xinit_check" #define PREFS_DONE_XINIT_CHECK "done_xinit_check"
#define PREFS_NO_QUIT_ALERT "no_quit_alert" #define PREFS_NO_QUIT_ALERT "no_quit_alert"
#define PREFS_OPTION_SENDS_ALT "option_sends_alt"
#define PREFS_FAKE_BUTTON2 "fake_button2" #define PREFS_FAKE_BUTTON2 "fake_button2"
#define PREFS_FAKE_BUTTON3 "fake_button3" #define PREFS_FAKE_BUTTON3 "fake_button3"
#define PREFS_APPKIT_MODIFIERS "appkit_modifiers" #define PREFS_APPKIT_MODIFIERS "appkit_modifiers"

View File

@ -712,10 +712,13 @@ static NSMutableArray * cfarray_to_nsarray (CFArrayRef in) {
default:quartzEnableRootless]; default:quartzEnableRootless];
quartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU quartzFullscreenMenu = [self prefs_get_boolean:@PREFS_FULLSCREEN_MENU
default:quartzFullscreenMenu]; default:quartzFullscreenMenu];
quartzFullscreenDisableHotkeys = ![self prefs_get_boolean: quartzFullscreenDisableHotkeys = ![self prefs_get_boolean:@PREFS_FULLSCREEN_HOTKEYS
@PREFS_FULLSCREEN_HOTKEYS default:!quartzFullscreenDisableHotkeys]; default:!quartzFullscreenDisableHotkeys];
darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS darwinFakeButtons = [self prefs_get_boolean:@PREFS_FAKEBUTTONS
default:darwinFakeButtons]; default:darwinFakeButtons];
quartzOptionSendsAlt = [self prefs_get_boolean:@PREFS_OPTION_SENDS_ALT
default:quartzOptionSendsAlt];
if (darwinFakeButtons) { if (darwinFakeButtons) {
const char *fake2, *fake3; const char *fake2, *fake3;
@ -969,8 +972,7 @@ void X11ApplicationMain (int argc, char **argv, char **envp) {
fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n"); fprintf(stderr, "X11ApplicationMain: Unable to determine KLGetCurrentKeyboardLayout() at startup.\n");
#endif #endif
memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap)); if (!QuartsResyncKeymap(FALSE)) {
if (!QuartzReadSystemKeymap(&keyInfo)) {
fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n"); fprintf(stderr, "X11ApplicationMain: Could not build a valid keymap.\n");
} }
@ -1229,17 +1231,10 @@ static inline int ensure_flag(int flags, int device_independent, int device_depe
if(key_layout != last_key_layout) { if(key_layout != last_key_layout) {
last_key_layout = key_layout; last_key_layout = key_layout;
#endif #endif
/* Update keyInfo */ /* Update keyInfo */
pthread_mutex_lock(&keyInfo_mutex); if (!QuartsResyncKeymap(TRUE)) {
memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
if (!QuartzReadSystemKeymap(&keyInfo)) {
fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n"); fprintf(stderr, "sendX11NSEvent: Could not build a valid keymap.\n");
} }
pthread_mutex_unlock(&keyInfo_mutex);
/* Tell server thread to deal with new keyInfo */
DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
} }
} }

View File

@ -69,6 +69,7 @@ typedef unsigned int NSUInteger;
IBOutlet NSButton *use_sysbeep; IBOutlet NSButton *use_sysbeep;
IBOutlet NSButton *enable_keyequivs; IBOutlet NSButton *enable_keyequivs;
IBOutlet NSButton *sync_keymap; IBOutlet NSButton *sync_keymap;
IBOutlet NSButton *option_sends_alt;
IBOutlet NSButton *click_through; IBOutlet NSButton *click_through;
IBOutlet NSButton *focus_follows_mouse; IBOutlet NSButton *focus_follows_mouse;
IBOutlet NSButton *focus_on_new_window; IBOutlet NSButton *focus_on_new_window;

View File

@ -43,6 +43,7 @@
#include "darwin.h" #include "darwin.h"
#include "darwinEvents.h" #include "darwinEvents.h"
#include "quartz.h" #include "quartz.h"
#include "quartzKeyboard.h"
#include <X11/extensions/applewmconst.h> #include <X11/extensions/applewmconst.h>
#include "applewmExt.h" #include "applewmExt.h"
@ -630,49 +631,69 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
- (IBAction)prefs_changed:sender - (IBAction)prefs_changed:sender
{ {
BOOL pbproxy_active; if(!sender)
return;
darwinFakeButtons = [fake_buttons intValue]; if(sender == fake_buttons) {
quartzUseSysBeep = [use_sysbeep intValue]; darwinFakeButtons = [fake_buttons intValue];
X11EnableKeyEquivalents = [enable_keyequivs intValue]; [NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons];
darwinSyncKeymap = [sync_keymap intValue]; } else if(sender == use_sysbeep) {
quartzFullscreenMenu = [enable_fullscreen_menu intValue]; quartzUseSysBeep = [use_sysbeep intValue];
[NSApp prefs_set_boolean:@PREFS_SYSBEEP value:quartzUseSysBeep];
} else if(sender == enable_keyequivs) {
X11EnableKeyEquivalents = [enable_keyequivs intValue];
[NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:X11EnableKeyEquivalents];
} else if(sender == sync_keymap) {
darwinSyncKeymap = [sync_keymap intValue];
[NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap];
} else if(sender == enable_fullscreen_menu) {
quartzFullscreenMenu = [enable_fullscreen_menu intValue];
[NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:quartzFullscreenMenu];
} else if(sender == option_sends_alt) {
BOOL prev_opt_sends_alt = quartzOptionSendsAlt;
/* after adding prefs here, also add to [X11Application read_defaults] quartzOptionSendsAlt = [option_sends_alt intValue];
and prefs_show */ [NSApp prefs_set_boolean:@PREFS_OPTION_SENDS_ALT value:quartzOptionSendsAlt];
[NSApp prefs_set_boolean:@PREFS_FAKEBUTTONS value:darwinFakeButtons]; if(prev_opt_sends_alt != quartzOptionSendsAlt)
[NSApp prefs_set_boolean:@PREFS_SYSBEEP value:quartzUseSysBeep]; QuartsResyncKeymap(TRUE);
[NSApp prefs_set_boolean:@PREFS_KEYEQUIVS value:X11EnableKeyEquivalents]; } else if(sender == click_through) {
[NSApp prefs_set_boolean:@PREFS_SYNC_KEYMAP value:darwinSyncKeymap]; [NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through intValue]];
[NSApp prefs_set_boolean:@PREFS_FULLSCREEN_MENU value:quartzFullscreenMenu]; } else if(sender == focus_follows_mouse) {
[NSApp prefs_set_boolean:@PREFS_CLICK_THROUGH value:[click_through intValue]]; [NSApp prefs_set_boolean:@PREFS_FFM value:[focus_follows_mouse intValue]];
[NSApp prefs_set_boolean:@PREFS_FFM value:[focus_follows_mouse intValue]]; } else if(sender == focus_on_new_window) {
[NSApp prefs_set_boolean:@PREFS_FOCUS_ON_NEW_WINDOW value:[focus_on_new_window intValue]]; [NSApp prefs_set_boolean:@PREFS_FOCUS_ON_NEW_WINDOW value:[focus_on_new_window intValue]];
[NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]]; } else if(sender == enable_auth) {
[NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]]; [NSApp prefs_set_boolean:@PREFS_NO_AUTH value:![enable_auth intValue]];
[NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]]; } else if(sender == enable_tcp) {
[NSApp prefs_set_boolean:@PREFS_NO_TCP value:![enable_tcp intValue]];
} else if(sender == depth) {
[NSApp prefs_set_integer:@PREFS_DEPTH value:[depth selectedTag]];
} else if(sender == sync_pasteboard) {
BOOL pbproxy_active = [sync_pasteboard intValue];
[NSApp prefs_set_boolean:@PREFS_SYNC_PB value:pbproxy_active];
pbproxy_active = [sync_pasteboard intValue]; [sync_pasteboard_to_clipboard setEnabled:pbproxy_active];
[sync_pasteboard_to_primary setEnabled:pbproxy_active];
[sync_clipboard_to_pasteboard setEnabled:pbproxy_active];
[sync_primary_immediately setEnabled:pbproxy_active];
[NSApp prefs_set_boolean:@PREFS_SYNC_PB value:pbproxy_active]; // setEnabled doesn't do this...
[NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD value:[sync_pasteboard_to_clipboard intValue]]; [sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
[NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_PRIMARY value:[sync_pasteboard_to_primary intValue]]; [sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
[NSApp prefs_set_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB value:[sync_clipboard_to_pasteboard intValue]]; } else if(sender == sync_pasteboard_to_clipboard) {
[NSApp prefs_set_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT value:[sync_primary_immediately intValue]]; [NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_CLIPBOARD value:[sync_pasteboard_to_clipboard intValue]];
} else if(sender == sync_pasteboard_to_primary) {
[NSApp prefs_set_boolean:@PREFS_SYNC_PB_TO_PRIMARY value:[sync_pasteboard_to_primary intValue]];
} else if(sender == sync_clipboard_to_pasteboard) {
[NSApp prefs_set_boolean:@PREFS_SYNC_CLIPBOARD_TO_PB value:[sync_clipboard_to_pasteboard intValue]];
} else if(sender == sync_primary_immediately) {
[NSApp prefs_set_boolean:@PREFS_SYNC_PRIMARY_ON_SELECT value:[sync_primary_immediately intValue]];
}
[NSApp prefs_synchronize]; [NSApp prefs_synchronize];
[sync_pasteboard_to_clipboard setEnabled:pbproxy_active]; DarwinSendDDXEvent(kXquartzReloadPreferences, 0);
[sync_pasteboard_to_primary setEnabled:pbproxy_active];
[sync_clipboard_to_pasteboard setEnabled:pbproxy_active];
[sync_primary_immediately setEnabled:pbproxy_active];
// setEnabled doesn't do this...
[sync_text1 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
[sync_text2 setTextColor:pbproxy_active ? [NSColor controlTextColor] : [NSColor disabledControlTextColor]];
DarwinSendDDXEvent(kXquartzReloadPreferences, 0);
} }
- (IBAction) prefs_show:sender - (IBAction) prefs_show:sender
@ -683,6 +704,7 @@ objectValueForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
[use_sysbeep setIntValue:quartzUseSysBeep]; [use_sysbeep setIntValue:quartzUseSysBeep];
[enable_keyequivs setIntValue:X11EnableKeyEquivalents]; [enable_keyequivs setIntValue:X11EnableKeyEquivalents];
[sync_keymap setIntValue:darwinSyncKeymap]; [sync_keymap setIntValue:darwinSyncKeymap];
[option_sends_alt setIntValue:quartzOptionSendsAlt];
[click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH default:NO]]; [click_through setIntValue:[NSApp prefs_get_boolean:@PREFS_CLICK_THROUGH default:NO]];
[focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM default:NO]]; [focus_follows_mouse setIntValue:[NSApp prefs_get_boolean:@PREFS_FFM default:NO]];
[focus_on_new_window setIntValue:[NSApp prefs_get_boolean:@PREFS_FOCUS_ON_NEW_WINDOW default:YES]]; [focus_on_new_window setIntValue:[NSApp prefs_get_boolean:@PREFS_FOCUS_ON_NEW_WINDOW default:YES]];

View File

@ -63,6 +63,9 @@ defaults to the depth of the main display.
.B defaults write org.x.X11 sync_keymap -boolean true .B defaults write org.x.X11 sync_keymap -boolean true
Keep the X11 keymap up to date with the OSX system keymap. Keep the X11 keymap up to date with the OSX system keymap.
.TP 8 .TP 8
.B defaults write org.x.X11 option_sends_alt -boolean true
The Option key will send Alt_L and Alt_R instead of Mode_switch.
.TP 8
.B defaults write org.x.X11 sync_pasteboard -boolean true .B defaults write org.x.X11 sync_pasteboard -boolean true
Enable syncing between the OSX pasteboard and clipboard/primary selection buffers in X11. This option needs to be true for any of the other pasteboard sync options to have an effect. Enable syncing between the OSX pasteboard and clipboard/primary selection buffers in X11. This option needs to be true for any of the other pasteboard sync options to have an effect.
.TP 8 .TP 8

View File

@ -79,6 +79,7 @@ int aquaMenuBarHeight = 0;
QuartzModeProcsPtr quartzProcs = NULL; QuartzModeProcsPtr quartzProcs = NULL;
const char *quartzOpenGLBundle = NULL; const char *quartzOpenGLBundle = NULL;
int quartzFullscreenDisableHotkeys = TRUE; int quartzFullscreenDisableHotkeys = TRUE;
int quartzOptionSendsAlt = FALSE;
#if defined(RANDR) && !defined(FAKE_RANDR) #if defined(RANDR) && !defined(FAKE_RANDR)
Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) { Bool QuartzRandRGetInfo (ScreenPtr pScreen, Rotation *rotations) {

View File

@ -60,6 +60,7 @@ extern int focusOnNewWindow;
extern int quartzUseAGL; extern int quartzUseAGL;
extern int quartzEnableKeyEquivalents; extern int quartzEnableKeyEquivalents;
extern int quartzFullscreenDisableHotkeys; extern int quartzFullscreenDisableHotkeys;
extern int quartzOptionSendsAlt;
// Other shared data // Other shared data
extern int quartzServerVisible; extern int quartzServerVisible;

View File

@ -50,6 +50,7 @@
#include "quartzCommon.h" #include "quartzCommon.h"
#include "darwin.h" #include "darwin.h"
#include "darwinEvents.h"
#include "quartzKeyboard.h" #include "quartzKeyboard.h"
#include "quartzAudio.h" #include "quartzAudio.h"
@ -191,6 +192,12 @@ const static struct {
{UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */ {UKEYSYM (0x31b), XK_dead_horn}, /* COMBINING HORN */
}; };
typedef struct darwinKeyboardInfo_struct {
CARD8 modMap[MAP_LENGTH];
KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY];
unsigned char modifierKeycodes[32][2];
} darwinKeyboardInfo;
darwinKeyboardInfo keyInfo; darwinKeyboardInfo keyInfo;
pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER; pthread_mutex_t keyInfo_mutex = PTHREAD_MUTEX_INITIALIZER;
@ -255,7 +262,8 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
case XK_Alt_L: case XK_Alt_L:
info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
info->modMap[MIN_KEYCODE + i] = Mod1Mask; info->modMap[MIN_KEYCODE + i] = Mod1Mask;
*k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. if(!quartzOptionSendsAlt)
*k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
break; break;
case XK_Alt_R: case XK_Alt_R:
@ -264,7 +272,8 @@ static void DarwinBuildModifierMaps(darwinKeyboardInfo *info) {
#else #else
info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i; info->modifierKeycodes[NX_MODIFIERKEY_ALTERNATE][0] = i;
#endif #endif
*k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor. if(!quartzOptionSendsAlt)
*k = XK_Mode_switch; // Yes, this is ugly. This needs to be cleaned up when we integrate quartzKeyboard with this code and refactor.
info->modMap[MIN_KEYCODE + i] = Mod1Mask; info->modMap[MIN_KEYCODE + i] = Mod1Mask;
break; break;
@ -647,7 +656,7 @@ static KeySym make_dead_key(KeySym in) {
return in; return in;
} }
Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) { static Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) {
#if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050 #if !defined(__LP64__) || MAC_OS_X_VERSION_MIN_REQUIRED < 1050
KeyboardLayoutRef key_layout; KeyboardLayoutRef key_layout;
int is_uchr = 1; int is_uchr = 1;
@ -824,3 +833,18 @@ Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info) {
return TRUE; return TRUE;
} }
Bool QuartsResyncKeymap(Bool sendDDXEvent) {
Bool retval;
/* Update keyInfo */
pthread_mutex_lock(&keyInfo_mutex);
memset(keyInfo.keyMap, 0, sizeof(keyInfo.keyMap));
retval = QuartzReadSystemKeymap(&keyInfo);
pthread_mutex_unlock(&keyInfo_mutex);
/* Tell server thread to deal with new keyInfo */
if(sendDDXEvent)
DarwinSendDDXEvent(kXquartzReloadKeymap, 0);
return retval;
}

View File

@ -41,18 +41,10 @@
#define MIN_KEYCODE XkbMinLegalKeyCode // unfortunately, this isn't 0... #define MIN_KEYCODE XkbMinLegalKeyCode // unfortunately, this isn't 0...
#define MAX_KEYCODE NUM_KEYCODES + MIN_KEYCODE - 1 #define MAX_KEYCODE NUM_KEYCODES + MIN_KEYCODE - 1
typedef struct darwinKeyboardInfo_struct {
CARD8 modMap[MAP_LENGTH];
KeySym keyMap[MAP_LENGTH * GLYPHS_PER_KEY];
unsigned char modifierKeycodes[32][2];
} darwinKeyboardInfo;
/* These functions need to be implemented by Xquartz, XDarwin, etc. */ /* These functions need to be implemented by Xquartz, XDarwin, etc. */
Bool QuartzReadSystemKeymap(darwinKeyboardInfo *info); Bool QuartsResyncKeymap(Bool sendDDXEvent);
/* Provided for darwinEvents.c */ /* Provided for darwinEvents.c */
extern darwinKeyboardInfo keyInfo;
extern pthread_mutex_t keyInfo_mutex;
void DarwinKeyboardReloadHandler(void); void DarwinKeyboardReloadHandler(void);
int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide); int DarwinModifierNXKeycodeToNXKey(unsigned char keycode, int *outSide);
int DarwinModifierNXKeyToNXKeycode(int key, int side); int DarwinModifierNXKeyToNXKeycode(int key, int side);