Added readme and keyboard handler example files

This commit is contained in:
seibelj 2017-01-05 16:00:11 -05:00
parent 6d5fba0cbb
commit bc6c9c7093
5 changed files with 177 additions and 12 deletions

View File

@ -0,0 +1,10 @@
#import <UIKit/UIKit.h>
#include <allegro5/allegro.h>
@interface KeyboardHandleriOS : UIView <UIKeyInput>
-(void)setCustomKeyboardEventSource:(ALLEGRO_EVENT_SOURCE*)ev_src;
-(void)show;
-(void)hide;
@end

View File

@ -0,0 +1,120 @@
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#endif
#import "KeyboardHandleriOS.h"
#include <allegro5/allegro.h>
#include <allegro5/allegro_iphone_objc.h>
@interface KeyboardHandleriOS()
{
ALLEGRO_EVENT_SOURCE *event_source;
ALLEGRO_DISPLAY *current_display;
}
@end
@implementation KeyboardHandleriOS
- (id)init {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
self = [self initWithFrame:CGRectMake(-100, -100, 0, 0)];
event_source = NULL;
current_display = al_get_current_display();
UIView* v = al_iphone_get_view(current_display);
[v addSubview:self];
return self;
}
- (void)setCustomKeyboardEventSource:(ALLEGRO_EVENT_SOURCE *)ev_src {
event_source = ev_src;
}
- (UIKeyboardType) keyboardType
{
return UIKeyboardTypeASCIICapable;
}
- (UITextAutocorrectionType) autocorrectionType
{
return UITextAutocorrectionTypeNo;
}
-(BOOL)canBecomeFirstResponder {
return YES;
}
- (void)deleteBackward {
if (!event_source) {
NSLog(@"deleteBackward(): No event source found, not sending events");
return;
}
ALLEGRO_EVENT *event_down = (ALLEGRO_EVENT*)calloc(1, sizeof(ALLEGRO_EVENT));
ALLEGRO_EVENT *event_up = (ALLEGRO_EVENT*)calloc(1, sizeof(ALLEGRO_EVENT));
event_down->type = ALLEGRO_EVENT_KEY_DOWN;
event_down->keyboard.display = current_display;
event_down->keyboard.keycode = ALLEGRO_KEY_BACKSPACE;
event_up->type = ALLEGRO_EVENT_KEY_UP;
event_up->keyboard.display = current_display;
event_up->keyboard.keycode = ALLEGRO_KEY_BACKSPACE;
al_emit_user_event(event_source, event_down, NULL);
al_emit_user_event(event_source, event_up, NULL);
free(event_down);
free(event_up);
}
- (BOOL)hasText {
return YES;
}
- (void)insertText:(NSString *)text
{
if (!event_source) {
NSLog(@"insertText(): No event source found, not sending events");
return;
}
ALLEGRO_EVENT *event_down = (ALLEGRO_EVENT*)calloc(1, sizeof(ALLEGRO_EVENT));
ALLEGRO_EVENT *event_up = (ALLEGRO_EVENT*)calloc(1, sizeof(ALLEGRO_EVENT));
if([text isEqualToString:@"\n"])
{
event_down->type = ALLEGRO_EVENT_KEY_DOWN;
event_down->keyboard.display = current_display;
event_down->keyboard.keycode = ALLEGRO_KEY_ENTER;
event_up->type = ALLEGRO_EVENT_KEY_UP;
event_up->keyboard.display = current_display;
event_up->keyboard.keycode = ALLEGRO_KEY_ENTER;
al_emit_user_event(event_source, event_down, NULL);
al_emit_user_event(event_source, event_up, NULL);
[self hide];
//m_kb->setDonePressed();
}
else {
event_down->type = ALLEGRO_EVENT_KEY_CHAR;
event_down->keyboard.display = current_display;
event_down->keyboard.unichar = [text characterAtIndex:0];
// doesn't matter what keycode is, nuklear backend ignores it as long as it
// isn't a special key
event_down->keyboard.keycode = ALLEGRO_KEY_A;
al_emit_user_event(event_source, event_down, NULL);
}
free(event_down);
free(event_up);
}
-(void)show {
NSLog(@"Should be showing!");
[self performSelectorOnMainThread:@selector(becomeFirstResponder) withObject:nil waitUntilDone:YES];
}
-(void)hide {
NSLog(@"Should be hiding!");
[self performSelectorOnMainThread:@selector(resignFirstResponder) withObject:nil waitUntilDone:YES];
}
- (void)keyboardDidHide:(NSNotification *)notification {
NSLog(@"keyboardDidHide called");
}
-(void)dealloc {
[[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidHideNotification object:nil];
}
@end

View File

@ -3,8 +3,6 @@ BIN = demo
# Flags
CFLAGS = -std=c99 -pedantic -O2
# DEBUG
#CFLAGS = -std=c99 -pedantic -O0 -g
SRC = main.c
OBJ = $(SRC:.c=.o)

26
demo/allegro5/Readme.md Normal file
View File

@ -0,0 +1,26 @@
# Allegro v5 nuklear backend
This backend provides support for [Allegro version 5](http://liballeg.org/). It works on on all supported platforms with an OpenGL backend, including iOS and Android.
Touch support is provided by handling the first touch (ignoring any extra simultaneous touches) and emitting nuklear mouse events. nuklear will handle only the first touch like a single left-mouse click. Dragging the touch screen emits mouse-move events.
## Compiling
You must link with image, font, ttf, and primitives Allegro addons. See the `Makefile`.
## Resolutions
Like every nuklear backend, handling many different resolutions and resolution densities can be tricky. 14px font on a desktop may be perfect, but extremely small on a retina iPad. I recommend writing a middleware that will detect what kind of screen is being used, and modify the sizes of widgets accordingly.
## Soft Keyboard for Touch Screen Devices
For keyboard support on devices without hardware keyboards (iOS, Android, etc.) you should define `NK_INCLUDE_DYNAMIC_SOFT_KEYBOARD` and pass open and close keyboard functions to `nk_allegro5_init()`. See the `main.c` demo for more information.
Information on how to implement soft keyboard callbacks for Android can be on the Allegro community wiki: https://wiki.allegro.cc/index.php?title=Running_Allegro_applications_on_Android#Displaying_the_Android_keyboard
To display a soft keyboard on iOS, you must create a `UIView` subclass that implements the `UIKeyInput` interface. See `KeyboardHandleriOS.h` and `KeyboardHandleriOS.m` Objective-C source code files for an example on how to do this. As the Allegro keyboard driver does not currently listen for iOS events, we use a custom event emitter to emit keyboard events, which is passed in after initialization with `(void)setCustomKeyboardEventSource:(ALLEGRO_EVENT_SOURCE *)ev_src`. This causes normal keyboard events to be emitted and properly caught by the nuklear backend. The provided `main.c` demo file does not implement this, but with the provided source code files it is not difficult to do. See this Allegro community forum thread for more information: https://www.allegro.cc/forums/thread/616672
### Manual Soft Keyboard Dismissal
As the user can dismiss a keyboard manually, nuklear will not be aware when this occurs, and the text edit cursor will think the entry field is still active. I recommend catching the dismiss event, then emitting `ALLEGRO_EVENT_TOUCH_BEGIN` and `ALLEGRO_EVENT_TOUCH_END` events in an unused portion of the screen (like the bottom-right corner). This will simulate the user touching outside of the text entry widget, which will make the edit field inactive.
### The Keyboard Covers Widgets
If you have a widget near the bottom of the screen, the keyboard opening woll cover it, and the user won't see what they are entering. One way to handle this is to make all text edit widgets view-only, and when tapped you dynamically create a new widget above the keyboard that receives all the key strokes. When the user dismisses the keyboard, copy the result from the new widget into the existing read-only text view and destroy the dynamic one.

View File

@ -19,6 +19,9 @@
#define NK_INCLUDE_STANDARD_IO
#define NK_INCLUDE_STANDARD_VARARGS
#define NK_INCLUDE_DEFAULT_ALLOCATOR
/* Uncomment this for iOS / Android keyboard support
#define NK_INCLUDE_DYNAMIC_SOFT_KEYBOARD
*/
#define NK_IMPLEMENTATION
#define NK_ALLEGRO5_IMPLEMENTATION
#include "../../nuklear.h"
@ -51,6 +54,20 @@
static void error_callback(int e, const char *d)
{printf("Error %d: %s\n", e, d);}
/* If NK_INCLUDE_DYNAMIC_SOFT_KEYBOARD is enabled, implement these
two methods and pass them as the last 2 arguments to nk_allegro5_init()
to have nuklear call them when appropriate.
void open_soft_keyboard()
{
[implement opening keyboard code]
}
void close_soft_keyboard()
{
[implement close keyboard code]
}
*/
int main(void)
{
/* Platform */
@ -87,19 +104,13 @@ int main(void)
al_register_event_source(event_queue, al_get_keyboard_event_source());
NkAllegro5Font *font;
font = nk_allegro5_font_create_from_file("../../extra_font/Roboto-Regular.ttf", 12, 0);
font = nk_allegro5_font_create_from_file("../../../extra_font/Roboto-Regular.ttf", 12, 0);
struct nk_context *ctx;
/* If NK_INCLUDE_DYNAMIC_SOFT_KEYBOARD is enabled, pass open_soft_keyboard and
close_soft_keyboard as the last 2 arguments to nk_allegro5_init() instead
of NULL, NULL */
ctx = nk_allegro5_init(font, display, WINDOW_WIDTH, WINDOW_HEIGHT, NULL, NULL);
/* Load Fonts: if none of these are loaded a default font will be used */
/* Load Cursor: if you uncomment cursor loading please hide the cursor */
/*struct nk_font *droid = nk_font_atlas_add_from_file(atlas, "../../../extra_font/DroidSans.ttf", 14, 0);*/
/*struct nk_font *roboto = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Roboto-Regular.ttf", 14, 0);*/
/*struct nk_font *future = nk_font_atlas_add_from_file(atlas, "../../../extra_font/kenvector_future_thin.ttf", 13, 0);*/
/*struct nk_font *clean = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyClean.ttf", 12, 0);*/
/*struct nk_font *tiny = nk_font_atlas_add_from_file(atlas, "../../../extra_font/ProggyTiny.ttf", 10, 0);*/
/*struct nk_font *cousine = nk_font_atlas_add_from_file(atlas, "../../../extra_font/Cousine-Regular.ttf", 13, 0);*/
/* style.c */
/*set_style(ctx, THEME_WHITE);*/