Search
lxdream.org :: lxdream :: r770:429ff505c450
lxdream 0.9.1
released Jun 29
Download Now
changeset770:429ff505c450
parent769:f7f62bea4cad
child771:749f0f4575d2
authornkeynes
dateMon Jul 28 03:41:25 2008 +0000 (15 years ago)
Implement key-binding configuration pane for Cocoa UI
Minor tweaks for consistency and static-correctness
src/cocoaui/cocoa_ctrl.c
src/cocoaui/cocoa_path.c
src/cocoaui/cocoa_prefs.c
src/cocoaui/cocoaui.c
src/cocoaui/cocoaui.h
src/display.c
src/display.h
src/drivers/video_gtk.c
src/drivers/video_osx.c
src/gtkui/gtk_ctrl.c
src/maple/controller.c
src/maple/kbd.c
src/maple/maple.c
src/maple/maple.h
src/maple/mouse.c
1.1 --- a/src/cocoaui/cocoa_ctrl.c Mon Jul 28 00:27:32 2008 +0000
1.2 +++ b/src/cocoaui/cocoa_ctrl.c Mon Jul 28 03:41:25 2008 +0000
1.3 @@ -18,10 +18,254 @@
1.4
1.5 #include "cocoaui.h"
1.6 #include "config.h"
1.7 +#include "display.h"
1.8 #include "maple/maple.h"
1.9
1.10 +#include <glib/gstrfuncs.h>
1.11 +
1.12 #define MAX_DEVICES 4
1.13
1.14 +static void cocoa_config_keysym_hook(void *data, const gchar *keysym);
1.15 +
1.16 +@interface KeyBindingEditor (Private)
1.17 +- (void)updateKeysym: (const gchar *)sym;
1.18 +@end
1.19 +
1.20 +@implementation KeyBindingEditor
1.21 +- (id)init
1.22 +{
1.23 + self = [super init];
1.24 + isPrimed = NO;
1.25 + lastValue = nil;
1.26 + [self setFieldEditor: YES];
1.27 + [self setEditable: FALSE];
1.28 + return self;
1.29 +}
1.30 +- (void)dealloc
1.31 +{
1.32 + if( lastValue != nil ) {
1.33 + [lastValue release];
1.34 + lastValue = nil;
1.35 + }
1.36 + [super dealloc];
1.37 +}
1.38 +- (void)setPrimed: (BOOL)primed
1.39 +{
1.40 + if( primed != isPrimed ) {
1.41 + isPrimed = primed;
1.42 + if( primed ) {
1.43 + lastValue = [[NSString stringWithString: [self string]] retain];
1.44 + [self setString: @"<press key>"];
1.45 + input_set_keysym_hook(cocoa_config_keysym_hook, self);
1.46 + } else {
1.47 + [lastValue release];
1.48 + lastValue = nil;
1.49 + input_set_keysym_hook(NULL,NULL);
1.50 + }
1.51 + }
1.52 +}
1.53 +- (void)fireBindingChanged
1.54 +{
1.55 + id delegate = [self delegate];
1.56 + if( delegate != nil && [delegate respondsToSelector:@selector(textDidChange:)] ) {
1.57 + [delegate textDidChange: [NSNotification notificationWithName: NSTextDidChangeNotification object: self]];
1.58 + }
1.59 +}
1.60 +
1.61 +- (void)updateKeysym: (const gchar *)sym
1.62 +{
1.63 + if( sym != NULL ) {
1.64 + [self setString: [NSString stringWithCString: sym]];
1.65 + [self setPrimed: NO];
1.66 + [self fireBindingChanged];
1.67 + }
1.68 +}
1.69 +- (void)keyPressed: (int)keycode
1.70 +{
1.71 + gchar *keysym = input_keycode_to_keysym(NULL, keycode);
1.72 + if( keysym != NULL ) {
1.73 + [self updateKeysym: keysym];
1.74 + g_free(keysym);
1.75 + }
1.76 +}
1.77 +- (void)insertText:(id)string
1.78 +{
1.79 + // Do nothing
1.80 +}
1.81 +- (void)mouseDown: (NSEvent *)event
1.82 +{
1.83 + [self setPrimed: YES];
1.84 + [super mouseDown: event];
1.85 +}
1.86 +- (void)keyDown: (NSEvent *) event
1.87 +{
1.88 + NSString *chars = [event characters];
1.89 + if( isPrimed ) {
1.90 + if( chars != NULL && [chars length] == 1 && [chars characterAtIndex: 0] == 27 ) {
1.91 + // Escape char = abort change
1.92 + [self setString: lastValue];
1.93 + [self setPrimed: NO];
1.94 + } else {
1.95 + [self keyPressed: ([event keyCode]+1)];
1.96 + }
1.97 + } else {
1.98 + if( chars != NULL && [chars length] == 1 ) {
1.99 + int ch = [chars characterAtIndex: 0];
1.100 + switch( ch ) {
1.101 + case 0x7F:
1.102 + [self setString: @""];
1.103 + [self fireBindingChanged];
1.104 + break;
1.105 + case '\r':
1.106 + [self setPrimed: YES];
1.107 + break;
1.108 + default:
1.109 + [super keyDown: event];
1.110 + break;
1.111 + }
1.112 + } else {
1.113 + [super keyDown: event];
1.114 + }
1.115 + }
1.116 +}
1.117 +- (void)flagsChanged: (NSEvent *) event
1.118 +{
1.119 + if( isPrimed ) {
1.120 + [self keyPressed: ([event keyCode]+1)];
1.121 + }
1.122 + [super flagsChanged: event];
1.123 +}
1.124 +@end
1.125 +
1.126 +static void cocoa_config_keysym_hook(void *data, const gchar *keysym)
1.127 +{
1.128 + KeyBindingEditor *editor = (KeyBindingEditor *)data;
1.129 + [editor updateKeysym: keysym];
1.130 +}
1.131 +
1.132 +
1.133 +@implementation KeyBindingField
1.134 +@end
1.135 +
1.136 +/*************************** Key-binding sub-view ***********************/
1.137 +
1.138 +#define MAX_KEY_BINDINGS 32
1.139 +
1.140 +@interface ControllerKeyBindingView : NSView
1.141 +{
1.142 + maple_device_t device;
1.143 + KeyBindingField *field[MAX_KEY_BINDINGS][2];
1.144 +}
1.145 +- (id)initWithFrame: (NSRect)frameRect;
1.146 +- (void)setDevice: (maple_device_t)device;
1.147 +@end
1.148 +
1.149 +@implementation ControllerKeyBindingView
1.150 +- (id)initWithFrame: (NSRect)frameRect
1.151 +{
1.152 + if( [super initWithFrame: frameRect] == nil ) {
1.153 + return nil;
1.154 + } else {
1.155 + device = NULL;
1.156 + return self;
1.157 + }
1.158 +}
1.159 +- (BOOL)isFlipped
1.160 +{
1.161 + return YES;
1.162 +}
1.163 +- (void)removeSubviews
1.164 +{
1.165 + [[self subviews] makeObjectsPerformSelector: @selector(removeFromSuperview)];
1.166 +}
1.167 +- (void)controlTextDidChange: (NSNotification *)notify
1.168 +{
1.169 + int binding = [[notify object] tag];
1.170 + NSString *val1 = [field[binding][0] stringValue];
1.171 + NSString *val2 = [field[binding][1] stringValue];
1.172 + char buf[ [val1 length] + [val2 length] + 2 ];
1.173 + const gchar *p = NULL;
1.174 +
1.175 + if( [val1 length] == 0 ) {
1.176 + if( [val2 length] != 0 ) {
1.177 + p = [val2 UTF8String];
1.178 + }
1.179 + } else if( [val2 length] == 0 ) {
1.180 + p = [val1 UTF8String];
1.181 + } else {
1.182 + sprintf( buf, "%s,%s", [val1 UTF8String], [val2 UTF8String] );
1.183 + p = buf;
1.184 + }
1.185 + maple_set_device_config_value( device, binding, p );
1.186 + lxdream_save_config();
1.187 +}
1.188 +- (void)setDevice: (maple_device_t)newDevice
1.189 +{
1.190 + device = newDevice;
1.191 + [self removeSubviews];
1.192 + if( device != NULL ) {
1.193 + lxdream_config_entry_t config = maple_get_device_config(device);
1.194 + if( config != NULL ) {
1.195 + int count, i, y, x;
1.196 +
1.197 + for( count=0; config[count].key != NULL; count++ );
1.198 + x = TEXT_GAP;
1.199 + NSSize size = NSMakeSize(85*3+TEXT_GAP*4, count*(TEXT_HEIGHT+TEXT_GAP)+TEXT_GAP);
1.200 + [self setFrameSize: size];
1.201 + [self scrollRectToVisible: NSMakeRect(0,0,1,1)];
1.202 + y = TEXT_GAP;
1.203 + for( i=0; config[i].key != NULL; i++ ) {
1.204 + NSRect frame = NSMakeRect(x, y + 2, 85, LABEL_HEIGHT);
1.205 + NSTextField *label = cocoa_gui_add_label(self, NS_(config[i].label), frame);
1.206 + [label setAlignment: NSRightTextAlignment];
1.207 +
1.208 + frame = NSMakeRect( x + 85 + TEXT_GAP, y, 85, TEXT_HEIGHT);
1.209 + field[i][0] = [[KeyBindingField alloc] initWithFrame: frame];
1.210 + [field[i][0] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.211 + [field[i][0] setTag: i];
1.212 + [field[i][0] setDelegate: self];
1.213 + [self addSubview: field[i][0]];
1.214 +
1.215 + frame = NSMakeRect( x + (85*2) + (TEXT_GAP*2), y, 85, TEXT_HEIGHT);
1.216 + field[i][1] = [[KeyBindingField alloc] initWithFrame: frame];
1.217 + [field[i][1] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.218 + [field[i][1] setTag: i];
1.219 + [field[i][1] setDelegate: self];
1.220 + [self addSubview: field[i][1]];
1.221 +
1.222 + if( config[i].value != NULL ) {
1.223 + gchar **parts = g_strsplit(config[i].value,",",3);
1.224 + if( parts[0] != NULL ) {
1.225 + [field[i][0] setStringValue: [NSString stringWithCString: parts[0]]];
1.226 + if( parts[1] != NULL ) {
1.227 + [field[i][1] setStringValue: [NSString stringWithCString: parts[1]]];
1.228 + }
1.229 + }
1.230 + g_strfreev(parts);
1.231 + }
1.232 +
1.233 + y += (TEXT_HEIGHT + TEXT_GAP);
1.234 + }
1.235 + } else {
1.236 + [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];
1.237 + }
1.238 + } else {
1.239 + [self setFrameSize: NSMakeSize(100,TEXT_HEIGHT+TEXT_GAP) ];
1.240 + }
1.241 +}
1.242 +@end
1.243 +
1.244 +/*************************** Top-level controller pane ***********************/
1.245 +
1.246 +@interface LxdreamPrefsControllerPane: LxdreamPrefsPane
1.247 +{
1.248 + struct maple_device *save_controller[4];
1.249 + NSButton *radio[4];
1.250 + ControllerKeyBindingView *key_bindings;
1.251 +}
1.252 ++ (LxdreamPrefsControllerPane *)new;
1.253 +@end
1.254 +
1.255 @implementation LxdreamPrefsControllerPane
1.256 + (LxdreamPrefsControllerPane *)new
1.257 {
1.258 @@ -35,19 +279,46 @@
1.259 const struct maple_device_class **devices = maple_get_device_classes();
1.260 char buf[16];
1.261 int i,j;
1.262 - int height = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;
1.263 + int y = [self contentHeight] - TEXT_HEIGHT - TEXT_GAP;
1.264 +
1.265 + NSBox *rule = [[NSBox alloc] initWithFrame:
1.266 + NSMakeRect(210+(TEXT_GAP*3), 1, 1, [self contentHeight] + TEXT_GAP - 2)];
1.267 + [rule setAutoresizingMask: (NSViewMaxXMargin|NSViewHeightSizable)];
1.268 + [rule setBoxType: NSBoxSeparator];
1.269 + [self addSubview: rule];
1.270 +
1.271 + NSRect bindingFrame = NSMakeRect(210+(TEXT_GAP*4), 0,
1.272 + frameRect.size.width - (210+(TEXT_GAP*4)), [self contentHeight] + TEXT_GAP );
1.273 + NSScrollView *scrollView = [[NSScrollView alloc] initWithFrame: bindingFrame];
1.274 + key_bindings = [[ControllerKeyBindingView alloc] initWithFrame: bindingFrame ];
1.275 + [scrollView setAutoresizingMask: (NSViewWidthSizable|NSViewHeightSizable)];
1.276 + [scrollView setDocumentView: key_bindings];
1.277 + [scrollView setDrawsBackground: NO];
1.278 + [scrollView setHasVerticalScroller: YES];
1.279 + [scrollView setAutohidesScrollers: YES];
1.280 +
1.281 + [self addSubview: scrollView];
1.282 + [key_bindings setDevice: maple_get_device(0,0)];
1.283 +
1.284 for( i=0; i<MAX_DEVICES; i++ ) {
1.285 + int x = TEXT_GAP;
1.286 save_controller[i] = NULL;
1.287 maple_device_t device = maple_get_device(i,0);
1.288 - NSRect frame = NSMakeRect( TEXT_GAP, height -((TEXT_HEIGHT+TEXT_GAP)*i - 2),
1.289 - 50, LABEL_HEIGHT );
1.290 +
1.291 snprintf( buf, sizeof(buf), _("Slot %d."), i );
1.292 - NSTextField *label = [self addLabel: [NSString stringWithUTF8String: buf]
1.293 - withFrame: frame ];
1.294 - [label setAlignment: NSRightTextAlignment];
1.295 - frame = NSMakeRect( 50 + (TEXT_GAP*2), height - ((TEXT_HEIGHT+TEXT_GAP)*i),
1.296 - 150, TEXT_HEIGHT );
1.297 - NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: frame pullsDown: NO];
1.298 + radio[i] = [[NSButton alloc] initWithFrame: NSMakeRect( x, y, 60, TEXT_HEIGHT )];
1.299 + [radio[i] setTitle: [NSString stringWithUTF8String: buf]];
1.300 + [radio[i] setTag: i];
1.301 + [radio[i] setButtonType: NSRadioButton];
1.302 + [radio[i] setAlignment: NSRightTextAlignment];
1.303 + [radio[i] setTarget: self];
1.304 + [radio[i] setAction: @selector(radioChanged:)];
1.305 + [radio[i] setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.306 + [self addSubview: radio[i]];
1.307 + x += 60 + TEXT_GAP;
1.308 +
1.309 + NSPopUpButton *popup = [[NSPopUpButton alloc] initWithFrame: NSMakeRect(x,y,150,TEXT_HEIGHT)
1.310 + pullsDown: NO];
1.311 [popup addItemWithTitle: NS_("<empty>")];
1.312 [popup setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
1.313 [[popup itemAtIndex: 0] setTag: 0];
1.314 @@ -62,16 +333,38 @@
1.315 [popup setAction: @selector(deviceChanged:)];
1.316 [popup setTag: i];
1.317 [self addSubview: popup];
1.318 + y -= (TEXT_HEIGHT+TEXT_GAP);
1.319 }
1.320 +
1.321 + [radio[0] setState: NSOnState];
1.322 return self;
1.323 }
1.324 }
1.325 +- (void)radioChanged: (id)sender
1.326 +{
1.327 + int slot = [sender tag];
1.328 + int i;
1.329 + for( i=0; i<MAX_DEVICES; i++ ) {
1.330 + if( i != slot ) {
1.331 + [radio[i] setState: NSOffState];
1.332 + }
1.333 + }
1.334 + [key_bindings setDevice: maple_get_device(slot,0)];
1.335 +}
1.336 - (void)deviceChanged: (id)sender
1.337 {
1.338 int slot = [sender tag];
1.339 - int new_device_idx = [sender indexOfSelectedItem] - 1;
1.340 + int new_device_idx = [sender indexOfSelectedItem] - 1, i;
1.341 maple_device_class_t new_device_class = NULL;
1.342
1.343 + for( i=0; i<MAX_DEVICES; i++ ) {
1.344 + if( i == slot ) {
1.345 + [radio[i] setState: NSOnState];
1.346 + } else {
1.347 + [radio[i] setState: NSOffState];
1.348 + }
1.349 + }
1.350 +
1.351 maple_device_t current = maple_get_device(slot,0);
1.352 maple_device_t new_device = NULL;
1.353 if( new_device_idx != -1 ) {
1.354 @@ -79,6 +372,7 @@
1.355 }
1.356 if( current == NULL ? new_device_class == NULL : current->device_class == new_device_class ) {
1.357 // No change
1.358 + [key_bindings setDevice: current];
1.359 return;
1.360 }
1.361 if( current != NULL && current->device_class == &controller_class ) {
1.362 @@ -95,7 +389,12 @@
1.363 }
1.364 maple_attach_device(new_device,slot,0);
1.365 }
1.366 -
1.367 + [key_bindings setDevice: maple_get_device(slot,0)];
1.368 lxdream_save_config();
1.369 }
1.370 @end
1.371 +
1.372 +NSView *cocoa_gui_create_prefs_controller_pane()
1.373 +{
1.374 + return [LxdreamPrefsControllerPane new];
1.375 +}
2.1 --- a/src/cocoaui/cocoa_path.c Mon Jul 28 00:27:32 2008 +0000
2.2 +++ b/src/cocoaui/cocoa_path.c Mon Jul 28 03:41:25 2008 +0000
2.3 @@ -19,7 +19,11 @@
2.4 #include "cocoaui.h"
2.5 #include "config.h"
2.6
2.7 -
2.8 +@interface LxdreamPrefsPathPane: LxdreamPrefsPane
2.9 +{
2.10 +}
2.11 ++ (LxdreamPrefsPathPane *)new;
2.12 +@end
2.13
2.14 @implementation LxdreamPrefsPathPane
2.15 + (LxdreamPrefsPathPane *)new
2.16 @@ -39,7 +43,7 @@
2.17 if( entry->label != NULL ) {
2.18 NSRect frame = NSMakeRect( TEXT_GAP, height -((TEXT_HEIGHT+TEXT_GAP)*i - 2),
2.19 150, LABEL_HEIGHT );
2.20 - NSTextField *label = [self addLabel: NS_(entry->label) withFrame: frame];
2.21 + NSTextField *label = cocoa_gui_add_label(self, NS_(entry->label), frame);
2.22 [label setAlignment: NSRightTextAlignment];
2.23
2.24 frame = NSMakeRect( 150 + (TEXT_GAP*2),
2.25 @@ -70,3 +74,9 @@
2.26 }
2.27 }
2.28 @end
2.29 +
2.30 +
2.31 +NSView *cocoa_gui_create_prefs_path_pane()
2.32 +{
2.33 + return [LxdreamPrefsPathPane new];
2.34 +}
3.1 --- a/src/cocoaui/cocoa_prefs.c Mon Jul 28 00:27:32 2008 +0000
3.2 +++ b/src/cocoaui/cocoa_prefs.c Mon Jul 28 03:41:25 2008 +0000
3.3 @@ -23,17 +23,6 @@
3.4 static LxdreamPrefsPanel *prefs_panel = NULL;
3.5
3.6 @implementation LxdreamPrefsPane
3.7 -- (NSTextField *)addLabel: (NSString *)text withFrame: (NSRect)frame
3.8 -{
3.9 - NSTextField *label = [[NSTextField alloc] initWithFrame: frame];
3.10 - [label setStringValue: text];
3.11 - [label setBordered: NO];
3.12 - [label setDrawsBackground: NO];
3.13 - [label setEditable: NO];
3.14 - [label setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
3.15 - [self addSubview: label];
3.16 - return label;
3.17 -}
3.18 - (int)contentHeight
3.19 {
3.20 return [self frame].size.height - headerHeight;
3.21 @@ -49,9 +38,9 @@
3.22 NSFont *titleFont = [NSFont fontWithName: @"Helvetica-Bold" size: 16.0];
3.23 NSRect fontRect = [titleFont boundingRectForFont];
3.24 int titleHeight = fontRect.size.height + [titleFont descender];
3.25 - NSTextField *label = [self addLabel: title withFrame:
3.26 + NSTextField *label = cocoa_gui_add_label(self, title,
3.27 NSMakeRect( TEXT_GAP, height-titleHeight,
3.28 - frameRect.size.width - (TEXT_GAP*2), titleHeight )];
3.29 + frameRect.size.width - (TEXT_GAP*2), titleHeight ));
3.30 [label setFont: titleFont];
3.31 height -= (titleHeight + TEXT_GAP);
3.32
3.33 @@ -67,6 +56,7 @@
3.34 }
3.35 @end
3.36
3.37 +/**************************** Main preferences window ************************/
3.38
3.39 @interface LxdreamPrefsPanel (Private)
3.40 - (void) initToolbar;
3.41 @@ -93,18 +83,37 @@
3.42 } else {
3.43 [self setTitle: NS_("Preferences")];
3.44 [self setDelegate: self];
3.45 + [self setMinSize: NSMakeSize(400,300)];
3.46 [self initToolbar];
3.47 - path_pane = [LxdreamPrefsPathPane new];
3.48 - ctrl_pane = [LxdreamPrefsControllerPane new];
3.49 -
3.50 + path_pane = cocoa_gui_create_prefs_path_pane();
3.51 + ctrl_pane = cocoa_gui_create_prefs_controller_pane();
3.52 + binding_editor = nil;
3.53 [self setContentView: path_pane];
3.54 return self;
3.55 }
3.56 }
3.57 +- (void)dealloc
3.58 +{
3.59 + if( binding_editor != nil ) {
3.60 + [binding_editor release];
3.61 + binding_editor = nil;
3.62 + }
3.63 + [super dealloc];
3.64 +}
3.65 - (void)windowWillClose: (NSNotification *)notice
3.66 {
3.67 prefs_panel = NULL;
3.68 }
3.69 +- (id)windowWillReturnFieldEditor:(NSWindow *)sender toObject:(id)view
3.70 +{
3.71 + if( [view isKindOfClass: [KeyBindingField class]] ) {
3.72 + if( binding_editor == nil ) {
3.73 + binding_editor = [[[KeyBindingEditor alloc] init] retain];
3.74 + }
3.75 + return binding_editor;
3.76 + }
3.77 + return nil;
3.78 +}
3.79 - (void) initToolbar
3.80 {
3.81 NSToolbar *toolbar = [[NSToolbar alloc] initWithIdentifier: @"LxdreamPrefsToolbar"];
4.1 --- a/src/cocoaui/cocoaui.c Mon Jul 28 00:27:32 2008 +0000
4.2 +++ b/src/cocoaui/cocoaui.c Mon Jul 28 03:41:25 2008 +0000
4.3 @@ -378,6 +378,8 @@
4.4 modes: [NSArray arrayWithObject: NSDefaultRunLoopMode] ];
4.5 }
4.6
4.7 +/*************************** Convenience methods ***************************/
4.8 +
4.9 NSImage *NSImage_new_from_framebuffer( frame_buffer_t buffer )
4.10 {
4.11 NSBitmapImageRep *rep =
4.12 @@ -392,3 +394,18 @@
4.13 [image addRepresentation: rep];
4.14 return image;
4.15 }
4.16 +
4.17 +
4.18 +NSTextField *cocoa_gui_add_label( NSView *parent, NSString *text, NSRect frame )
4.19 +{
4.20 + NSTextField *label = [[NSTextField alloc] initWithFrame: frame];
4.21 + [label setStringValue: text];
4.22 + [label setBordered: NO];
4.23 + [label setDrawsBackground: NO];
4.24 + [label setEditable: NO];
4.25 + [label setAutoresizingMask: (NSViewMinYMargin|NSViewMaxXMargin)];
4.26 + if( parent != NULL ) {
4.27 + [parent addSubview: label];
4.28 + }
4.29 + return label;
4.30 +}
5.1 --- a/src/cocoaui/cocoaui.h Mon Jul 28 00:27:32 2008 +0000
5.2 +++ b/src/cocoaui/cocoaui.h Mon Jul 28 03:41:25 2008 +0000
5.3 @@ -38,6 +38,13 @@
5.4 NSMenu *cocoa_gdrom_menu_new();
5.5 NSView *video_osx_create_drawable();
5.6 void cocoa_gui_show_preferences();
5.7 +NSView *cocoa_gui_create_prefs_controller_pane();
5.8 +NSView *cocoa_gui_create_prefs_path_pane();
5.9 +
5.10 +/**
5.11 + * Convenience method to create a new text label in the specified parent.
5.12 + */
5.13 +NSTextField *cocoa_gui_add_label(NSView *parent, NSString *title, NSRect frame);
5.14
5.15 @interface LxdreamMainWindow : NSWindow
5.16 {
5.17 @@ -57,36 +64,32 @@
5.18 int headerHeight;
5.19 }
5.20 - (id)initWithFrame: (NSRect)frameRect title:(NSString *)title;
5.21 -/**
5.22 - * Create a text label and add it to the pane
5.23 - */
5.24 -- (NSTextField *)addLabel: (NSString *)text withFrame: (NSRect)frame;
5.25 - (int)contentHeight;
5.26 @end
5.27
5.28 +@interface KeyBindingEditor: NSTextView
5.29 +{
5.30 + BOOL isPrimed;
5.31 + NSString *lastValue;
5.32 +}
5.33 +@end
5.34 +
5.35 +@interface KeyBindingField : NSTextField
5.36 +{
5.37 +}
5.38 +@end
5.39 +
5.40 @interface LxdreamPrefsPanel : NSPanel
5.41 {
5.42 NSArray *toolbar_ids;
5.43 NSArray *toolbar_defaults;
5.44 NSDictionary *toolbar_items;
5.45 NSView *path_pane, *ctrl_pane;
5.46 + KeyBindingEditor *binding_editor;
5.47 }
5.48 - (id)initWithContentRect:(NSRect)contentRect;
5.49 @end
5.50
5.51 -@interface LxdreamPrefsPathPane: LxdreamPrefsPane
5.52 -{
5.53 -}
5.54 -+ (LxdreamPrefsPathPane *)new;
5.55 -@end
5.56 -
5.57 -@interface LxdreamPrefsControllerPane: LxdreamPrefsPane
5.58 -{
5.59 - struct maple_device *save_controller[4];
5.60 -}
5.61 -+ (LxdreamPrefsControllerPane *)new;
5.62 -@end
5.63 -
5.64 #ifdef __cplusplus
5.65 }
5.66 #endif
6.1 --- a/src/display.c Mon Jul 28 00:27:32 2008 +0000
6.2 +++ b/src/display.c Mon Jul 28 03:41:25 2008 +0000
6.3 @@ -218,7 +218,7 @@
6.4 return NULL;
6.5 }
6.6
6.7 -static gchar *input_keysym_for_keycode( input_driver_t driver, uint16_t keycode )
6.8 +gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode )
6.9 {
6.10 if( keycode == 0 ) {
6.11 return NULL;
6.12 @@ -386,7 +386,7 @@
6.13 }
6.14 }
6.15 if( display_keysym_hook != NULL ) {
6.16 - gchar *sym = input_keysym_for_keycode( driver, keycode );
6.17 + gchar *sym = input_keycode_to_keysym( driver, keycode );
6.18 if( sym != NULL ) {
6.19 display_keysym_hook(display_keysym_hook_data, sym);
6.20 g_free(sym);
7.1 --- a/src/display.h Mon Jul 28 00:27:32 2008 +0000
7.2 +++ b/src/display.h Mon Jul 28 03:41:25 2008 +0000
7.3 @@ -314,6 +314,12 @@
7.4
7.5 void input_event_mouse( uint32_t buttons, int32_t x_axis, int32_t y_axis );
7.6
7.7 +/**
7.8 + * Given a keycode and the originating input driver, return the corresponding
7.9 + * keysym. The caller is responsible for freeing the string.
7.10 + * @return a newly allocated string, or NULL of the keycode is unresolvable.
7.11 + */
7.12 +gchar *input_keycode_to_keysym( input_driver_t driver, uint16_t keycode );
7.13
7.14 typedef void (*display_keysym_callback_t)( void *data, const gchar *keysym );
7.15
8.1 --- a/src/drivers/video_gtk.c Mon Jul 28 00:27:32 2008 +0000
8.2 +++ b/src/drivers/video_gtk.c Mon Jul 28 03:41:25 2008 +0000
8.3 @@ -123,8 +123,9 @@
8.4 gboolean video_gtk_init();
8.5 void video_gtk_shutdown();
8.6 void video_gtk_display_blank( uint32_t colour );
8.7 -uint16_t video_gtk_resolve_keysym( const gchar *keysym );
8.8 -uint16_t video_gtk_keycode_to_dckeysym(uint16_t keycode);
8.9 +static uint16_t video_gtk_resolve_keysym( const gchar *keysym );
8.10 +static uint16_t video_gtk_keycode_to_dckeysym(uint16_t keycode);
8.11 +static gchar *video_gtk_get_keysym_for_keycode(uint16_t keycode);
8.12
8.13 struct display_driver display_gtk_driver = {
8.14 "gtk",
8.15 @@ -133,18 +134,10 @@
8.16 video_gtk_shutdown,
8.17 video_gtk_resolve_keysym,
8.18 video_gtk_keycode_to_dckeysym,
8.19 - NULL,
8.20 + video_gtk_keycode_to_keysym,
8.21 NULL, NULL, NULL, NULL, NULL,
8.22 video_gtk_display_blank, NULL };
8.23
8.24 -uint16_t video_gtk_resolve_keysym( const gchar *keysym )
8.25 -{
8.26 - int val = gdk_keyval_from_name( keysym );
8.27 - if( val == GDK_VoidSymbol )
8.28 - return 0;
8.29 - return (uint16_t)val;
8.30 -}
8.31 -
8.32 gboolean video_gtk_expose_callback(GtkWidget *widget, GdkEventExpose *event, gpointer data )
8.33 {
8.34 pvr2_redraw_display();
8.35 @@ -159,7 +152,20 @@
8.36 return TRUE;
8.37 }
8.38
8.39 -uint16_t video_gtk_keycode_to_dckeysym(uint16_t keycode)
8.40 +static uint16_t video_gtk_resolve_keysym( const gchar *keysym )
8.41 +{
8.42 + int val = gdk_keyval_from_name( keysym );
8.43 + if( val == GDK_VoidSymbol )
8.44 + return 0;
8.45 + return (uint16_t)val;
8.46 +}
8.47 +
8.48 +static gchar *video_gtk_get_keycode_to_keysym( uint16_t keycode )
8.49 +{
8.50 + return g_strdup(gdk_keyval_name(keycode));
8.51 +}
8.52 +
8.53 +static uint16_t video_gtk_keycode_to_dckeysym(uint16_t keycode)
8.54 {
8.55 if( keycode >= 'a' && keycode <= 'z' ) {
8.56 return (keycode - 'a') + DCKB_a;
9.1 --- a/src/drivers/video_osx.c Mon Jul 28 00:27:32 2008 +0000
9.2 +++ b/src/drivers/video_osx.c Mon Jul 28 03:41:25 2008 +0000
9.3 @@ -35,6 +35,7 @@
9.4 static void video_osx_display_blank( uint32_t colour );
9.5 static uint16_t video_osx_resolve_keysym( const gchar *keysym );
9.6 static uint16_t video_osx_keycode_to_dckeysym(uint16_t keycode);
9.7 +static gchar *video_osx_keycode_to_keysym(uint16_t keycode);
9.8
9.9 struct display_driver display_osx_driver = {
9.10 "osx",
9.11 @@ -42,7 +43,7 @@
9.12 video_osx_init, video_osx_shutdown,
9.13 video_osx_resolve_keysym,
9.14 video_osx_keycode_to_dckeysym,
9.15 - NULL,
9.16 + video_osx_keycode_to_keysym,
9.17 NULL, NULL, NULL, NULL, NULL,
9.18 video_osx_display_blank, NULL };
9.19
9.20 @@ -250,3 +251,11 @@
9.21 }
9.22 }
9.23
9.24 +static gchar *video_osx_keycode_to_keysym(uint16_t keycode)
9.25 +{
9.26 + if( keycode < 1 || keycode > 128 ) {
9.27 + return NULL;
9.28 + } else {
9.29 + return g_strdup(mac_keysyms_by_keycode[keycode-1]);
9.30 + }
9.31 +}
9.32 \ No newline at end of file
10.1 --- a/src/gtkui/gtk_ctrl.c Mon Jul 28 00:27:32 2008 +0000
10.2 +++ b/src/gtkui/gtk_ctrl.c Mon Jul 28 03:41:25 2008 +0000
10.3 @@ -136,7 +136,7 @@
10.4
10.5 static void controller_device_configure( maple_device_t device )
10.6 {
10.7 - lxdream_config_entry_t conf = device->get_config(device);
10.8 + lxdream_config_entry_t conf = maple_get_device_config(device);
10.9 int count, i;
10.10 for( count=0; conf[count].key != NULL; count++ );
10.11
10.12 @@ -152,7 +152,7 @@
10.13 x = 3;
10.14 y -= (count+1)>>1;
10.15 }
10.16 - gtk_table_attach( GTK_TABLE(table), gtk_label_new(conf[i].key), x, x+1, y, y+1,
10.17 + gtk_table_attach( GTK_TABLE(table), gtk_label_new(gettext(conf[i].label)), x, x+1, y, y+1,
10.18 GTK_SHRINK, GTK_SHRINK, 0, 0 );
10.19 text = gtk_entry_new();
10.20 gtk_entry_set_width_chars( GTK_ENTRY(text), 11 );
11.1 --- a/src/maple/controller.c Mon Jul 28 00:27:32 2008 +0000
11.2 +++ b/src/maple/controller.c Mon Jul 28 03:41:25 2008 +0000
11.3 @@ -17,34 +17,37 @@
11.4 */
11.5
11.6 #include <stdlib.h>
11.7 +#include <assert.h>
11.8 #include "dream.h"
11.9 #include "dreamcast.h"
11.10 #include "display.h"
11.11 #include "maple.h"
11.12 #include "maple/controller.h"
11.13
11.14 -#define CONTROLLER_CONFIG_ENTRIES 16
11.15 +#define CONTROLLER_CONFIG_ENTRIES 15
11.16
11.17 -void controller_attach( maple_device_t dev );
11.18 -void controller_detach( maple_device_t dev );
11.19 -void controller_destroy( maple_device_t dev );
11.20 -maple_device_t controller_clone( maple_device_t dev );
11.21 -maple_device_t controller_new();
11.22 -lxdream_config_entry_t controller_get_config( maple_device_t dev );
11.23 -int controller_get_cond( maple_device_t dev, int function, unsigned char *outbuf,
11.24 +static void controller_attach( maple_device_t dev );
11.25 +static void controller_detach( maple_device_t dev );
11.26 +static void controller_destroy( maple_device_t dev );
11.27 +static maple_device_t controller_clone( maple_device_t dev );
11.28 +static maple_device_t controller_new();
11.29 +static lxdream_config_entry_t controller_get_config( maple_device_t dev );
11.30 +static void controller_set_config_value( maple_device_t dev, unsigned int key, const gchar *value );
11.31 +static int controller_get_cond( maple_device_t dev, int function, unsigned char *outbuf,
11.32 unsigned int *outlen );
11.33
11.34 typedef struct controller_device {
11.35 struct maple_device dev;
11.36 uint32_t condition[2];
11.37 - struct lxdream_config_entry config[CONTROLLER_CONFIG_ENTRIES];
11.38 + struct lxdream_config_entry config[CONTROLLER_CONFIG_ENTRIES+1];
11.39 } *controller_device_t;
11.40
11.41 struct maple_device_class controller_class = { "Sega Controller", controller_new };
11.42
11.43 static struct controller_device base_controller = {
11.44 { MAPLE_DEVICE_TAG, &controller_class, CONTROLLER_IDENT, CONTROLLER_VERSION,
11.45 - controller_get_config, controller_attach, controller_detach, controller_destroy,
11.46 + controller_get_config, controller_set_config_value,
11.47 + controller_attach, controller_detach, controller_destroy,
11.48 controller_clone, NULL, NULL, controller_get_cond, NULL, NULL, NULL },
11.49 {0x0000FFFF, 0x80808080},
11.50 {{ "dpad left", N_("Dpad left"), CONFIG_TYPE_KEY },
11.51 @@ -64,16 +67,21 @@
11.52 { "start", N_("Start button"), CONFIG_TYPE_KEY },
11.53 { NULL, CONFIG_TYPE_NONE }} };
11.54
11.55 +static int config_button_map[] = {
11.56 + BUTTON_DPAD_LEFT, BUTTON_DPAD_RIGHT, BUTTON_DPAD_UP, BUTTON_DPAD_DOWN,
11.57 + JOY_LEFT, JOY_RIGHT, JOY_UP, JOY_DOWN, BUTTON_X, BUTTON_Y, BUTTON_A,
11.58 + BUTTON_B, BUTTON_LEFT_TRIGGER, BUTTON_RIGHT_TRIGGER, BUTTON_START };
11.59 +
11.60 #define CONTROLLER(x) ((controller_device_t)(x))
11.61
11.62 -maple_device_t controller_new( )
11.63 +static maple_device_t controller_new( )
11.64 {
11.65 controller_device_t dev = malloc( sizeof(struct controller_device) );
11.66 memcpy( dev, &base_controller, sizeof(base_controller) );
11.67 return MAPLE_DEVICE(dev);
11.68 }
11.69
11.70 -maple_device_t controller_clone( maple_device_t srcdevice )
11.71 +static maple_device_t controller_clone( maple_device_t srcdevice )
11.72 {
11.73 controller_device_t src = (controller_device_t)srcdevice;
11.74 controller_device_t dev = (controller_device_t)controller_new();
11.75 @@ -85,7 +93,7 @@
11.76 /**
11.77 * Input callback
11.78 */
11.79 -void controller_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
11.80 +static void controller_key_callback( void *mdev, uint32_t value, uint32_t pressure, gboolean isKeyDown )
11.81 {
11.82 controller_device_t dev = (controller_device_t)mdev;
11.83 if( isKeyDown ) {
11.84 @@ -129,13 +137,23 @@
11.85 }
11.86 }
11.87
11.88 -lxdream_config_entry_t controller_get_config( maple_device_t mdev )
11.89 +static lxdream_config_entry_t controller_get_config( maple_device_t mdev )
11.90 {
11.91 controller_device_t dev = (controller_device_t)mdev;
11.92 return dev->config;
11.93 }
11.94
11.95 -void controller_destroy( maple_device_t mdev )
11.96 +static void controller_set_config_value( maple_device_t mdev, unsigned int key, const gchar *value )
11.97 +{
11.98 + controller_device_t dev = (controller_device_t)mdev;
11.99 + assert( key < CONTROLLER_CONFIG_ENTRIES );
11.100 +
11.101 + input_unregister_key( dev->config[key].value, controller_key_callback, dev, config_button_map[key] );
11.102 + lxdream_set_config_value( &dev->config[key], value );
11.103 + input_register_key( dev->config[key].value, controller_key_callback, dev, config_button_map[key] );
11.104 +}
11.105 +
11.106 +static void controller_destroy( maple_device_t mdev )
11.107 {
11.108 free( mdev );
11.109 }
11.110 @@ -144,49 +162,27 @@
11.111 * Device is being attached to the bus. Go through the config and reserve the
11.112 * keys we need.
11.113 */
11.114 -void controller_attach( maple_device_t mdev )
11.115 +static void controller_attach( maple_device_t mdev )
11.116 {
11.117 controller_device_t dev = (controller_device_t)mdev;
11.118 - input_register_key( dev->config[0].value, controller_key_callback, dev, BUTTON_DPAD_LEFT );
11.119 - input_register_key( dev->config[1].value, controller_key_callback, dev, BUTTON_DPAD_RIGHT );
11.120 - input_register_key( dev->config[2].value, controller_key_callback, dev, BUTTON_DPAD_UP );
11.121 - input_register_key( dev->config[3].value, controller_key_callback, dev, BUTTON_DPAD_DOWN );
11.122 - input_register_key( dev->config[4].value, controller_key_callback, dev, JOY_LEFT );
11.123 - input_register_key( dev->config[5].value, controller_key_callback, dev, JOY_RIGHT );
11.124 - input_register_key( dev->config[6].value, controller_key_callback, dev, JOY_UP );
11.125 - input_register_key( dev->config[7].value, controller_key_callback, dev, JOY_DOWN );
11.126 - input_register_key( dev->config[8].value, controller_key_callback, dev, BUTTON_X );
11.127 - input_register_key( dev->config[9].value, controller_key_callback, dev, BUTTON_Y );
11.128 - input_register_key( dev->config[10].value, controller_key_callback, dev, BUTTON_A );
11.129 - input_register_key( dev->config[11].value, controller_key_callback, dev, BUTTON_B );
11.130 - input_register_key( dev->config[12].value, controller_key_callback, dev, BUTTON_LEFT_TRIGGER );
11.131 - input_register_key( dev->config[13].value, controller_key_callback, dev, BUTTON_RIGHT_TRIGGER );
11.132 - input_register_key( dev->config[14].value, controller_key_callback, dev, BUTTON_START );
11.133 + int i;
11.134 + for( i=0; i<CONTROLLER_CONFIG_ENTRIES; i++ ) {
11.135 + input_register_key( dev->config[i].value, controller_key_callback, dev, config_button_map[i] );
11.136 + }
11.137 }
11.138
11.139 -void controller_detach( maple_device_t mdev )
11.140 +static void controller_detach( maple_device_t mdev )
11.141 {
11.142 controller_device_t dev = (controller_device_t)mdev;
11.143 - input_unregister_key( dev->config[0].value, controller_key_callback, dev, BUTTON_DPAD_LEFT );
11.144 - input_unregister_key( dev->config[1].value, controller_key_callback, dev, BUTTON_DPAD_RIGHT );
11.145 - input_unregister_key( dev->config[2].value, controller_key_callback, dev, BUTTON_DPAD_UP );
11.146 - input_unregister_key( dev->config[3].value, controller_key_callback, dev, BUTTON_DPAD_DOWN );
11.147 - input_unregister_key( dev->config[4].value, controller_key_callback, dev, JOY_LEFT );
11.148 - input_unregister_key( dev->config[5].value, controller_key_callback, dev, JOY_RIGHT );
11.149 - input_unregister_key( dev->config[6].value, controller_key_callback, dev, JOY_UP );
11.150 - input_unregister_key( dev->config[7].value, controller_key_callback, dev, JOY_DOWN );
11.151 - input_unregister_key( dev->config[8].value, controller_key_callback, dev, BUTTON_X );
11.152 - input_unregister_key( dev->config[9].value, controller_key_callback, dev, BUTTON_Y );
11.153 - input_unregister_key( dev->config[10].value, controller_key_callback, dev, BUTTON_A );
11.154 - input_unregister_key( dev->config[11].value, controller_key_callback, dev, BUTTON_B );
11.155 - input_unregister_key( dev->config[12].value, controller_key_callback, dev, BUTTON_LEFT_TRIGGER );
11.156 - input_unregister_key( dev->config[13].value, controller_key_callback, dev, BUTTON_RIGHT_TRIGGER );
11.157 - input_unregister_key( dev->config[14].value, controller_key_callback, dev, BUTTON_START );
11.158 + int i;
11.159 + for( i=0; i<CONTROLLER_CONFIG_ENTRIES; i++ ) {
11.160 + input_unregister_key( dev->config[i].value, controller_key_callback, dev, config_button_map[i] );
11.161 + }
11.162
11.163 }
11.164
11.165
11.166 -int controller_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
11.167 +static int controller_get_cond( maple_device_t mdev, int function, unsigned char *outbuf,
11.168 unsigned int *outlen )
11.169 {
11.170 controller_device_t dev = (controller_device_t)mdev;
12.1 --- a/src/maple/kbd.c Mon Jul 28 00:27:32 2008 +0000
12.2 +++ b/src/maple/kbd.c Mon Jul 28 03:41:25 2008 +0000
12.3 @@ -55,7 +55,7 @@
12.4
12.5 static struct keyboard_device base_keyboard = {
12.6 { MAPLE_DEVICE_TAG, &keyboard_class, KEYBOARD_IDENT, KEYBOARD_VERSION,
12.7 - NULL, keyboard_attach, keyboard_detach, maple_default_destroy,
12.8 + NULL, NULL, keyboard_attach, keyboard_detach, maple_default_destroy,
12.9 keyboard_clone, NULL, NULL, keyboard_get_cond, NULL, NULL, NULL },
12.10 {0,0,0,0,0,0,0,0},
12.11 };
13.1 --- a/src/maple/maple.c Mon Jul 28 00:27:32 2008 +0000
13.2 +++ b/src/maple/maple.c Mon Jul 28 03:41:25 2008 +0000
13.3 @@ -332,6 +332,13 @@
13.4 }
13.5 }
13.6
13.7 +void maple_set_device_config_value( maple_device_t dev, unsigned int key, const gchar *value )
13.8 +{
13.9 + if( dev != NULL && dev->set_config_value != NULL ) {
13.10 + dev->set_config_value( dev, key, value );
13.11 + }
13.12 +}
13.13 +
13.14 void maple_default_destroy( maple_device_t mdev )
13.15 {
13.16 free(mdev);
14.1 --- a/src/maple/maple.h Mon Jul 28 00:27:32 2008 +0000
14.2 +++ b/src/maple/maple.h Mon Jul 28 03:41:25 2008 +0000
14.3 @@ -76,6 +76,7 @@
14.4 unsigned char ident[112];
14.5 unsigned char version[80];
14.6 lxdream_config_entry_t (*get_config)(struct maple_device *dev);
14.7 + void (*set_config_value)(struct maple_device *dev, unsigned int key, const gchar *value);
14.8 void (*attach)(struct maple_device *dev);
14.9 void (*detach)(struct maple_device *dev);
14.10 void (*destroy)(struct maple_device *dev);
14.11 @@ -101,6 +102,7 @@
14.12 const struct maple_device_class *maple_get_device_class( const gchar *name );
14.13 const struct maple_device_class **maple_get_device_classes();
14.14 lxdream_config_entry_t maple_get_device_config( maple_device_t dev );
14.15 +void maple_set_device_config_value( maple_device_t dev, unsigned int key, const gchar *value );
14.16
14.17 void maple_handle_buffer( uint32_t buffer );
14.18 void maple_attach_device( maple_device_t dev, unsigned int port, unsigned int periph );
15.1 --- a/src/maple/mouse.c Mon Jul 28 00:27:32 2008 +0000
15.2 +++ b/src/maple/mouse.c Mon Jul 28 03:41:25 2008 +0000
15.3 @@ -58,7 +58,7 @@
15.4
15.5 static struct mouse_device base_mouse = {
15.6 { MAPLE_DEVICE_TAG, &mouse_class, MOUSE_IDENT, MOUSE_VERSION,
15.7 - NULL, mouse_attach, mouse_detach, maple_default_destroy,
15.8 + NULL, NULL, mouse_attach, mouse_detach, maple_default_destroy,
15.9 mouse_clone, NULL, NULL, mouse_get_cond, NULL, NULL, NULL },
15.10 0, {0,0,0,0,0,0,0,0},
15.11 };
.