You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and dots ('.'), can be up to 35 characters long. Letters must be lowercase.
		
		
		
		
		
			
		
			
				
					
					
						
							807 lines
						
					
					
						
							30 KiB
						
					
					
				
			
		
		
	
	
							807 lines
						
					
					
						
							30 KiB
						
					
					
				| // ImGui iOS+OpenGL+Synergy binding | |
| // In this binding, ImTextureID is used to store an OpenGL 'GLuint' texture identifier. Read the FAQ about ImTextureID in imgui.cpp. | |
| // Providing a standalone iOS application with Synergy integration makes this sample more verbose than others. It also hasn't been tested as much. | |
| // Refer to other examples to get an easier understanding of how to integrate ImGui into your existing application. | |
| 
 | |
| // TODO: | |
| // - Clipboard is not supported. | |
| 
 | |
| #import <OpenGLES/ES3/gl.h> | |
| #import <OpenGLES/ES3/glext.h> | |
| 
 | |
| #include <sys/time.h> | |
| #include <sys/types.h> | |
| #include <sys/socket.h> | |
| #include <netdb.h> | |
| 
 | |
| #include "imgui_impl_ios.h" | |
| #include "imgui.h" | |
| 
 | |
| #include "uSynergy.h" | |
| 
 | |
| // From Carbon HIToolbox/Events.h | |
| // FIXME: Keyboard mapping is hacked in because Synergy doesn't give us character but only keycode which aren't really portable if you consider keyboard locale. See https://github.com/ocornut/imgui/pull/247 | |
| enum { | |
|     kVK_ANSI_A                    = 0x00, | |
|     kVK_ANSI_S                    = 0x01, | |
|     kVK_ANSI_D                    = 0x02, | |
|     kVK_ANSI_F                    = 0x03, | |
|     kVK_ANSI_H                    = 0x04, | |
|     kVK_ANSI_G                    = 0x05, | |
|     kVK_ANSI_Z                    = 0x06, | |
|     kVK_ANSI_X                    = 0x07, | |
|     kVK_ANSI_C                    = 0x08, | |
|     kVK_ANSI_V                    = 0x09, | |
|     kVK_ANSI_B                    = 0x0B, | |
|     kVK_ANSI_Q                    = 0x0C, | |
|     kVK_ANSI_W                    = 0x0D, | |
|     kVK_ANSI_E                    = 0x0E, | |
|     kVK_ANSI_R                    = 0x0F, | |
|     kVK_ANSI_Y                    = 0x10, | |
|     kVK_ANSI_T                    = 0x11, | |
|     kVK_ANSI_1                    = 0x12, | |
|     kVK_ANSI_2                    = 0x13, | |
|     kVK_ANSI_3                    = 0x14, | |
|     kVK_ANSI_4                    = 0x15, | |
|     kVK_ANSI_6                    = 0x16, | |
|     kVK_ANSI_5                    = 0x17, | |
|     kVK_ANSI_Equal                = 0x18, | |
|     kVK_ANSI_9                    = 0x19, | |
|     kVK_ANSI_7                    = 0x1A, | |
|     kVK_ANSI_Minus                = 0x1B, | |
|     kVK_ANSI_8                    = 0x1C, | |
|     kVK_ANSI_0                    = 0x1D, | |
|     kVK_ANSI_RightBracket         = 0x1E, | |
|     kVK_ANSI_O                    = 0x1F, | |
|     kVK_ANSI_U                    = 0x20, | |
|     kVK_ANSI_LeftBracket          = 0x21, | |
|     kVK_ANSI_I                    = 0x22, | |
|     kVK_ANSI_P                    = 0x23, | |
|     kVK_ANSI_L                    = 0x25, | |
|     kVK_ANSI_J                    = 0x26, | |
|     kVK_ANSI_Quote                = 0x27, | |
|     kVK_ANSI_K                    = 0x28, | |
|     kVK_ANSI_Semicolon            = 0x29, | |
|     kVK_ANSI_Backslash            = 0x2A, | |
|     kVK_ANSI_Comma                = 0x2B, | |
|     kVK_ANSI_Slash                = 0x2C, | |
|     kVK_ANSI_N                    = 0x2D, | |
|     kVK_ANSI_M                    = 0x2E, | |
|     kVK_ANSI_Period               = 0x2F, | |
|     kVK_ANSI_Grave                = 0x32, | |
|     kVK_ANSI_KeypadDecimal        = 0x41, | |
|     kVK_ANSI_KeypadMultiply       = 0x43, | |
|     kVK_ANSI_KeypadPlus           = 0x45, | |
|     kVK_ANSI_KeypadClear          = 0x47, | |
|     kVK_ANSI_KeypadDivide         = 0x4B, | |
|     kVK_ANSI_KeypadEnter          = 0x4C, | |
|     kVK_ANSI_KeypadMinus          = 0x4E, | |
|     kVK_ANSI_KeypadEquals         = 0x51, | |
|     kVK_ANSI_Keypad0              = 0x52, | |
|     kVK_ANSI_Keypad1              = 0x53, | |
|     kVK_ANSI_Keypad2              = 0x54, | |
|     kVK_ANSI_Keypad3              = 0x55, | |
|     kVK_ANSI_Keypad4              = 0x56, | |
|     kVK_ANSI_Keypad5              = 0x57, | |
|     kVK_ANSI_Keypad6              = 0x58, | |
|     kVK_ANSI_Keypad7              = 0x59, | |
|     kVK_ANSI_Keypad8              = 0x5B, | |
|     kVK_ANSI_Keypad9              = 0x5C | |
| }; | |
| 
 | |
| /* keycodes for keys that are independent of keyboard layout*/ | |
| enum { | |
|     kVK_Return                    = 0x24, | |
|     kVK_Tab                       = 0x30, | |
|     kVK_Space                     = 0x31, | |
|     kVK_Delete                    = 0x33, | |
|     kVK_Escape                    = 0x35, | |
|     kVK_Command                   = 0x37, | |
|     kVK_Shift                     = 0x38, | |
|     kVK_CapsLock                  = 0x39, | |
|     kVK_Option                    = 0x3A, | |
|     kVK_Control                   = 0x3B, | |
|     kVK_RightShift                = 0x3C, | |
|     kVK_RightOption               = 0x3D, | |
|     kVK_RightControl              = 0x3E, | |
|     kVK_Function                  = 0x3F, | |
|     kVK_F17                       = 0x40, | |
|     kVK_VolumeUp                  = 0x48, | |
|     kVK_VolumeDown                = 0x49, | |
|     kVK_Mute                      = 0x4A, | |
|     kVK_F18                       = 0x4F, | |
|     kVK_F19                       = 0x50, | |
|     kVK_F20                       = 0x5A, | |
|     kVK_F5                        = 0x60, | |
|     kVK_F6                        = 0x61, | |
|     kVK_F7                        = 0x62, | |
|     kVK_F3                        = 0x63, | |
|     kVK_F8                        = 0x64, | |
|     kVK_F9                        = 0x65, | |
|     kVK_F11                       = 0x67, | |
|     kVK_F13                       = 0x69, | |
|     kVK_F16                       = 0x6A, | |
|     kVK_F14                       = 0x6B, | |
|     kVK_F10                       = 0x6D, | |
|     kVK_F12                       = 0x6F, | |
|     kVK_F15                       = 0x71, | |
|     kVK_Help                      = 0x72, | |
|     kVK_Home                      = 0x73, | |
|     kVK_PageUp                    = 0x74, | |
|     kVK_ForwardDelete             = 0x75, | |
|     kVK_F4                        = 0x76, | |
|     kVK_End                       = 0x77, | |
|     kVK_F2                        = 0x78, | |
|     kVK_PageDown                  = 0x79, | |
|     kVK_F1                        = 0x7A, | |
|     kVK_LeftArrow                 = 0x7B, | |
|     kVK_RightArrow                = 0x7C, | |
|     kVK_DownArrow                 = 0x7D, | |
|     kVK_UpArrow                   = 0x7E | |
| }; | |
| 
 | |
| static char g_keycodeCharUnshifted[256] = {}; | |
| static char g_keycodeCharShifted[256] = {}; | |
| 
 | |
| //static double       g_Time = 0.0f; | |
| static bool         g_MousePressed[3] = { false, false, false }; | |
| static float        g_mouseWheelX = 0.0f; | |
| static float        g_mouseWheelY = 0.0f; | |
| 
 | |
| static GLuint       g_FontTexture = 0; | |
| static int          g_ShaderHandle = 0, g_VertHandle = 0, g_FragHandle = 0; | |
| static int          g_AttribLocationTex = 0, g_AttribLocationProjMtx = 0; | |
| static int          g_AttribLocationPosition = 0, g_AttribLocationUV = 0, g_AttribLocationColor = 0; | |
| static size_t       g_VboSize = 0; | |
| static unsigned int g_VboHandle = 0, g_VaoHandle = 0; | |
| static float        g_displayScale; | |
| 
 | |
| static int usynergy_sockfd; | |
| static bool g_synergyPtrActive = false; | |
| static uint16_t g_mousePosX = 0; | |
| static uint16_t g_mousePosY = 0; | |
| 
 | |
| static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data); | |
| bool ImGui_ImplIOS_CreateDeviceObjects(); | |
| 
 | |
| static NSString *g_serverName; | |
| 
 | |
| uSynergyBool ImGui_ConnectFunc(uSynergyCookie cookie) | |
| { | |
|     // NOTE: You need to turn off "Use SSL Encryption" in Synergy preferences, since | |
|     // uSynergy does not support SSL. | |
|      | |
|     NSLog( @"Connect Func!"); | |
|     struct addrinfo hints, *res; | |
|      | |
|     // first, load up address structs with getaddrinfo(): | |
|     memset(&hints, 0, sizeof hints); | |
|     hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever | |
|     hints.ai_socktype = SOCK_STREAM; | |
|      | |
|     // get server address | |
|     getaddrinfo([g_serverName UTF8String], "24800", &hints, &res); | |
|      | |
|     if (!res) | |
|     { | |
|         NSLog( @"Could not find server: %@", g_serverName ); | |
|         return USYNERGY_FALSE; | |
|     } | |
|      | |
|     // make a socket: | |
|     usynergy_sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol); | |
|      | |
|     // connect it to the address and port we passed in to getaddrinfo(): | |
|     int ret = connect(usynergy_sockfd, res->ai_addr, res->ai_addrlen); | |
|     if (!ret) { | |
|         NSLog( @"Connect succeeded..."); | |
|     } else { | |
|         NSLog( @"Connect failed, %d", ret ); | |
|     } | |
|      | |
|      | |
|     return USYNERGY_TRUE; | |
| } | |
| 
 | |
| uSynergyBool ImGui_SendFunc(uSynergyCookie cookie, const uint8_t *buffer, int length) | |
| { | |
| //    NSLog( @"Send Func" ); | |
|     send( usynergy_sockfd, buffer, length, 0 ); | |
|      | |
|     return USYNERGY_TRUE; | |
| } | |
| 
 | |
| uSynergyBool ImGui_RecvFunc(uSynergyCookie cookie, uint8_t *buffer, int maxLength, int* outLength) | |
| { | |
|     *outLength = (int)recv( usynergy_sockfd, buffer, maxLength, 0 ); | |
|      | |
|     return USYNERGY_TRUE; | |
| } | |
| 
 | |
| void ImGui_SleepFunc(uSynergyCookie cookie, int timeMs) | |
| { | |
|     usleep( timeMs * 1000 ); | |
| } | |
| 
 | |
| uint32_t ImGui_GetTimeFunc() | |
| { | |
|     struct timeval  tv; | |
|     gettimeofday(&tv, NULL); | |
|      | |
|     return (int32_t)((tv.tv_sec) * 1000 + (tv.tv_usec) / 1000); | |
| } | |
| 
 | |
| void ImGui_TraceFunc(uSynergyCookie cookie, const char *text) | |
| { | |
|     puts(text); | |
| } | |
| 
 | |
| void ImGui_ScreenActiveCallback(uSynergyCookie cookie, uSynergyBool active) | |
| { | |
|     g_synergyPtrActive = active; | |
| //    printf( "Synergy: screen activate %s\n", active?"YES":"NO" ); | |
| } | |
| 
 | |
| void ImGui_MouseCallback(uSynergyCookie cookie, uint16_t x, uint16_t y, int16_t wheelX, int16_t wheelY, | |
|                          uSynergyBool buttonLeft, uSynergyBool buttonRight, uSynergyBool buttonMiddle) | |
| { | |
| //    printf("Synergy: mouse callback %d %d -- wheel %d %d\n", x, y,  wheelX, wheelY ); | |
|     uSynergyContext *ctx = (uSynergyContext*)cookie; | |
|     g_mousePosX = x; | |
|     g_mousePosY = y; | |
|     g_mouseWheelX = wheelX; | |
|     g_mouseWheelY = wheelY; | |
|     g_MousePressed[0] = buttonLeft; | |
|     g_MousePressed[1] = buttonMiddle; | |
|     g_MousePressed[2] = buttonRight; | |
|      | |
|     ctx->m_mouseWheelX = 0; | |
|     ctx->m_mouseWheelY = 0; | |
| } | |
| 
 | |
| void ImGui_KeyboardCallback(uSynergyCookie cookie, uint16_t key, | |
|                             uint16_t modifiers, uSynergyBool down, uSynergyBool repeat) | |
| { | |
|     int scanCode = key-1; | |
|     // printf("Synergy: keyboard callback: 0x%02X (%s)", scanCode, down?"true":"false"); | |
|     ImGuiIO& io = ImGui::GetIO(); | |
|     io.KeysDown[key] = down; | |
|     io.KeyShift = (modifiers & USYNERGY_MODIFIER_SHIFT); | |
|     io.KeyCtrl = (modifiers & USYNERGY_MODIFIER_CTRL); | |
|     io.KeyAlt = (modifiers & USYNERGY_MODIFIER_ALT); | |
|     io.KeySuper = (modifiers & USYNERGY_MODIFIER_WIN); | |
|      | |
|     // Add this as keyboard input | |
|     if ((down) && (key) && (scanCode<256) && !(modifiers & USYNERGY_MODIFIER_CTRL))  | |
| 	{ | |
|         // If this key maps to a character input, apply it | |
|         int charForKeycode = (modifiers & USYNERGY_MODIFIER_SHIFT) ? g_keycodeCharShifted[scanCode] : g_keycodeCharUnshifted[scanCode]; | |
|         io.AddInputCharacter((unsigned short)charForKeycode); | |
|     } | |
|      | |
| } | |
| 
 | |
| void ImGui_JoystickCallback(uSynergyCookie cookie, uint8_t joyNum, uint16_t buttons, int8_t leftStickX, int8_t leftStickY, int8_t rightStickX, int8_t rightStickY) | |
| { | |
|     printf("Synergy: joystick callback TODO\n"); | |
| } | |
| 
 | |
| void ImGui_ClipboardCallback(uSynergyCookie cookie, enum uSynergyClipboardFormat format, const uint8_t *data, uint32_t size) | |
| { | |
|     printf("Synergy: clipboard callback TODO\n" ); | |
| } | |
| 
 | |
| @interface ImGuiHelper () | |
| { | |
|     BOOL _mouseDown; | |
|     BOOL _mouseTapped; | |
|     CGPoint _touchPos; | |
| 
 | |
|     uSynergyContext _synergyCtx; | |
|     dispatch_queue_t _synergyQueue; | |
| } | |
| @property (nonatomic, weak) UIView *view; | |
| @property (nonatomic, strong) NSString *serverName; | |
| 
 | |
| @end | |
| 
 | |
| @implementation ImGuiHelper | |
| 
 | |
| - (id) initWithView: (UIView *)view | |
| { | |
|     self = [super init]; | |
|     if (self) | |
|     { | |
|         self.view = view; | |
| 
 | |
|         [self setupImGuiHooks]; | |
|     } | |
|     return self; | |
| } | |
| 
 | |
| - (void)setupKeymaps | |
| { | |
|     // The keyboard mapping is a big headache. I tried for a while to find a better way to do this, | |
|     // but this was the best I could come up with. There are some device independent API's available | |
|     // to convert scan codes to unicode characters, but these are only available on mac and not | |
|     // on iOS as far as I can tell (it's part of Carbon). I didn't see any better way to do | |
|     // this or  any way to get the character codes out of usynergy. | |
|     g_keycodeCharUnshifted[ kVK_ANSI_A ]='a'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_S ]='s'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_D ]='d'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_F ]='f'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_H ]='h'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_G ]='g'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Z ]='z'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_X ]='x'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_C ]='c'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_V ]='v'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_B ]='b'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Q ]='q'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_W ]='w'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_E ]='e'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_R ]='r'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Y ]='y'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_T ]='t'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_1 ]='1'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_2 ]='2'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_3 ]='3'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_4 ]='4'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_6 ]='6'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_5 ]='5'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Equal ]='='; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_9 ]='9'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_7 ]='7'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Minus ]='-'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_8 ]='8'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_0 ]='0'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_RightBracket ]=']'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_O ]='o'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_U ]='u'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_LeftBracket ]='['; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_I ]='i'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_P ]='p'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_L ]='l'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_J ]='j'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Quote ]='\''; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_K ]='k'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Semicolon ]=';'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Backslash ]='\\'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Comma ]=','; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Slash ]='/'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_N ]='n'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_M ]='m'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Period ]='.'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Grave ]='`'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadDecimal ]='.'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadMultiply ]='*'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadPlus ]='+'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadDivide ]='/'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadEnter ]='\n'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadMinus ]='-'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_KeypadEquals ]='='; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad0 ]='0'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad1 ]='1'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad2 ]='2'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad3 ]='3'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad4 ]='4'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad5 ]='5'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad6 ]='6'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad7 ]='7'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad8 ]='8'; | |
|     g_keycodeCharUnshifted[ kVK_ANSI_Keypad9 ]='9'; | |
|     g_keycodeCharUnshifted[ kVK_Space ]=' '; | |
|      | |
|     g_keycodeCharShifted[ kVK_ANSI_A ]='A'; | |
|     g_keycodeCharShifted[ kVK_ANSI_S ]='S'; | |
|     g_keycodeCharShifted[ kVK_ANSI_D ]='D'; | |
|     g_keycodeCharShifted[ kVK_ANSI_F ]='F'; | |
|     g_keycodeCharShifted[ kVK_ANSI_H ]='H'; | |
|     g_keycodeCharShifted[ kVK_ANSI_G ]='G'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Z ]='Z'; | |
|     g_keycodeCharShifted[ kVK_ANSI_X ]='X'; | |
|     g_keycodeCharShifted[ kVK_ANSI_C ]='C'; | |
|     g_keycodeCharShifted[ kVK_ANSI_V ]='V'; | |
|     g_keycodeCharShifted[ kVK_ANSI_B ]='B'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Q ]='Q'; | |
|     g_keycodeCharShifted[ kVK_ANSI_W ]='W'; | |
|     g_keycodeCharShifted[ kVK_ANSI_E ]='E'; | |
|     g_keycodeCharShifted[ kVK_ANSI_R ]='R'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Y ]='Y'; | |
|     g_keycodeCharShifted[ kVK_ANSI_T ]='T'; | |
|     g_keycodeCharShifted[ kVK_ANSI_1 ]='!'; | |
|     g_keycodeCharShifted[ kVK_ANSI_2 ]='@'; | |
|     g_keycodeCharShifted[ kVK_ANSI_3 ]='#'; | |
|     g_keycodeCharShifted[ kVK_ANSI_4 ]='$'; | |
|     g_keycodeCharShifted[ kVK_ANSI_6 ]='^'; | |
|     g_keycodeCharShifted[ kVK_ANSI_5 ]='%'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Equal ]='+'; | |
|     g_keycodeCharShifted[ kVK_ANSI_9 ]='('; | |
|     g_keycodeCharShifted[ kVK_ANSI_7 ]='&'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Minus ]='_'; | |
|     g_keycodeCharShifted[ kVK_ANSI_8 ]='*'; | |
|     g_keycodeCharShifted[ kVK_ANSI_0 ]=')'; | |
|     g_keycodeCharShifted[ kVK_ANSI_RightBracket ]='}'; | |
|     g_keycodeCharShifted[ kVK_ANSI_O ]='O'; | |
|     g_keycodeCharShifted[ kVK_ANSI_U ]='U'; | |
|     g_keycodeCharShifted[ kVK_ANSI_LeftBracket ]='{'; | |
|     g_keycodeCharShifted[ kVK_ANSI_I ]='I'; | |
|     g_keycodeCharShifted[ kVK_ANSI_P ]='P'; | |
|     g_keycodeCharShifted[ kVK_ANSI_L ]='L'; | |
|     g_keycodeCharShifted[ kVK_ANSI_J ]='J'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Quote ]='\"'; | |
|     g_keycodeCharShifted[ kVK_ANSI_K ]='K'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Semicolon ]=':'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Backslash ]='|'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Comma ]='<'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Slash ]='?'; | |
|     g_keycodeCharShifted[ kVK_ANSI_N ]='N'; | |
|     g_keycodeCharShifted[ kVK_ANSI_M ]='M'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Period ]='>'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Grave ]='~'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadDecimal ]='.'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadMultiply ]='*'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadPlus ]='+'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadDivide ]='/'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadEnter ]='\n'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadMinus ]='-'; | |
|     g_keycodeCharShifted[ kVK_ANSI_KeypadEquals ]='='; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad0 ]='0'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad1 ]='1'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad2 ]='2'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad3 ]='3'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad4 ]='4'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad5 ]='5'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad6 ]='6'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad7 ]='7'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad8 ]='8'; | |
|     g_keycodeCharShifted[ kVK_ANSI_Keypad9 ]='9'; | |
|     g_keycodeCharShifted[ kVK_Space ]=' '; | |
| } | |
| 
 | |
| - (void)setupImGuiHooks | |
| { | |
|     ImGuiIO &io = ImGui::GetIO(); | |
|      | |
|     [self setupKeymaps]; | |
|      | |
|     // Account for retina display for glScissor | |
|     g_displayScale = [[UIScreen mainScreen] scale]; | |
|      | |
|     ImGuiStyle &style = ImGui::GetStyle(); | |
|     style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); | |
|      | |
|     io.RenderDrawListsFn = ImGui_ImplIOS_RenderDrawLists; | |
|      | |
|     UIPanGestureRecognizer *panRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(viewDidPan:) ]; | |
|     [self.view addGestureRecognizer:panRecognizer]; | |
|      | |
|     UITapGestureRecognizer *tapRecoginzer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector( viewDidTap:)]; | |
|     [self.view addGestureRecognizer:tapRecoginzer]; | |
|      | |
|     // Fill out the Synergy key map | |
|     // (for some reason synergy scan codes are off by 1) | |
|     io.KeyMap[ImGuiKey_Tab] = kVK_Tab+1; | |
|     io.KeyMap[ImGuiKey_LeftArrow] = kVK_LeftArrow+1; | |
|     io.KeyMap[ImGuiKey_RightArrow] = kVK_RightArrow+1; | |
|     io.KeyMap[ImGuiKey_UpArrow] = kVK_UpArrow+1; | |
|     io.KeyMap[ImGuiKey_DownArrow] = kVK_DownArrow+1; | |
|     io.KeyMap[ImGuiKey_Home] = kVK_Home+1; | |
|     io.KeyMap[ImGuiKey_End] = kVK_End+1; | |
|     io.KeyMap[ImGuiKey_Insert] = kVK_Help+1; | |
|     io.KeyMap[ImGuiKey_Delete] = kVK_ForwardDelete+1; | |
|     io.KeyMap[ImGuiKey_Backspace] = kVK_Delete+1; | |
|     io.KeyMap[ImGuiKey_Enter] = kVK_Return+1; | |
|     io.KeyMap[ImGuiKey_Escape] = kVK_Escape+1; | |
|     io.KeyMap[ImGuiKey_A] = kVK_ANSI_A+1; | |
|     io.KeyMap[ImGuiKey_C] = kVK_ANSI_C+1; | |
|     io.KeyMap[ImGuiKey_V] = kVK_ANSI_V+1; | |
|     io.KeyMap[ImGuiKey_X] = kVK_ANSI_X+1; | |
|     io.KeyMap[ImGuiKey_Y] = kVK_ANSI_Y+1; | |
|     io.KeyMap[ImGuiKey_Z] = kVK_ANSI_Z+1; | |
| } | |
| 
 | |
| - (void)connectServer: (NSString*)serverName | |
| { | |
|     self.serverName = serverName; | |
|     g_serverName = serverName; | |
|      | |
|     // Init synergy | |
|     NSString *bundleName = [[[NSBundle mainBundle] infoDictionary] objectForKey:(NSString*)kCFBundleNameKey]; | |
|      | |
|     uSynergyInit( &_synergyCtx ); | |
|     _synergyCtx.m_clientName = strdup( [bundleName UTF8String] ); | |
|     _synergyCtx.m_clientWidth = self.view.bounds.size.width; | |
|     _synergyCtx.m_clientHeight = self.view.bounds.size.height; | |
|      | |
|     _synergyCtx.m_connectFunc = ImGui_ConnectFunc; | |
|     _synergyCtx.m_sendFunc = ImGui_SendFunc; | |
|     _synergyCtx.m_receiveFunc = ImGui_RecvFunc; | |
|     _synergyCtx.m_sleepFunc = ImGui_SleepFunc; | |
|     _synergyCtx.m_traceFunc = ImGui_TraceFunc; | |
|     _synergyCtx.m_getTimeFunc = ImGui_GetTimeFunc; | |
|      | |
|     _synergyCtx.m_traceFunc = ImGui_TraceFunc; | |
|     _synergyCtx.m_screenActiveCallback = ImGui_ScreenActiveCallback; | |
|     _synergyCtx.m_mouseCallback = ImGui_MouseCallback; | |
|     _synergyCtx.m_keyboardCallback = ImGui_KeyboardCallback; | |
|      | |
|     _synergyCtx.m_cookie = (uSynergyCookie)&_synergyCtx; | |
|      | |
|     // Create a background thread for synergy | |
|     _synergyQueue = dispatch_queue_create( "imgui-usynergy", NULL ); | |
|     dispatch_async( _synergyQueue, ^{ | |
|         while (1) { | |
|             uSynergyUpdate( &_synergyCtx ); | |
|         } | |
|     }); | |
| } | |
| 
 | |
| 
 | |
| - (void)viewDidPan: (UIPanGestureRecognizer *)recognizer | |
| { | |
|      | |
|     if ((recognizer.state == UIGestureRecognizerStateBegan) || | |
|         (recognizer.state == UIGestureRecognizerStateChanged)) | |
|     { | |
|         _mouseDown = YES; | |
|         _touchPos = [recognizer locationInView:self.view]; | |
|     } | |
|     else | |
|     { | |
|         _mouseDown = NO; | |
|         _touchPos = CGPointMake( -1, -1 ); | |
|     } | |
| } | |
| 
 | |
| - (void)viewDidTap: (UITapGestureRecognizer*)recognizer | |
| { | |
|     _touchPos = [recognizer locationInView:self.view]; | |
|     _mouseTapped = YES; | |
| } | |
|      | |
| - (void)render | |
| { | |
|     ImGui::Render(); | |
| } | |
| 
 | |
| - (void)newFrame | |
| { | |
|     ImGuiIO& io = ImGui::GetIO(); | |
|     ImGuiStyle &style = ImGui::GetStyle(); | |
|      | |
|     if (!g_FontTexture) | |
|     { | |
|         ImGui_ImplIOS_CreateDeviceObjects(); | |
|     } | |
|      | |
|     io.DisplaySize = ImVec2( _view.bounds.size.width, _view.bounds.size.height ); | |
| 
 | |
|     io.MouseDrawCursor = g_synergyPtrActive; | |
|     if (g_synergyPtrActive) | |
|     { | |
|         style.TouchExtraPadding = ImVec2( 0.0, 0.0 ); | |
|         io.MousePos = ImVec2( g_mousePosX, g_mousePosY ); | |
|         for (int i=0; i < 3; i++) | |
|         { | |
|             io.MouseDown[i] = g_MousePressed[i]; | |
|         } | |
| 
 | |
|         // This is an arbitrary scaling factor that works for me. Not sure what units these mousewheel values from synergy are supposed to be in. | |
|         io.MouseWheel = g_mouseWheelY / 500.0; | |
|         io.MouseWheelH = g_mouseWheelX / 500.0; | |
|     } | |
|     else | |
|     { | |
|         // Synergy not active, use touch events | |
|         style.TouchExtraPadding = ImVec2( 4.0, 4.0 ); | |
|         io.MousePos = ImVec2(_touchPos.x, _touchPos.y ); | |
|         if ((_mouseDown) || (_mouseTapped)) | |
|         { | |
|             io.MouseDown[0] = true; | |
|             _mouseTapped = NO; | |
|         } | |
|         else | |
|         { | |
|             io.MouseDown[0] = false; | |
|         } | |
|     } | |
|      | |
|     ImGui::NewFrame(); | |
| } | |
| @end | |
| 
 | |
| // This is the main rendering function that you have to implement and provide to ImGui (via setting up 'RenderDrawListsFn' in the ImGuiIO structure) | |
| // If text or lines are blurry when integrating ImGui in your engine: | |
| // - in your Render function, try translating your projection matrix by (0.5f,0.5f) or (0.375f,0.375f) | |
| // NOTE: this is copied pretty much entirely from the opengl3_example, with only minor changes for ES | |
| static void ImGui_ImplIOS_RenderDrawLists (ImDrawData *draw_data) | |
| { | |
|     // Setup render state: alpha-blending enabled, no face culling, no depth testing, scissor enabled | |
| 	// FIXME: Backport changes from imgui_impl_glfw_gl3.cpp | |
|     GLint last_program, last_texture; | |
|     glGetIntegerv(GL_CURRENT_PROGRAM, &last_program); | |
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | |
|     glEnable(GL_BLEND); | |
|     glBlendEquation(GL_FUNC_ADD); | |
|     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); | |
|      | |
|     glDisable(GL_CULL_FACE); | |
|     glDisable(GL_DEPTH_TEST); | |
|     glEnable(GL_SCISSOR_TEST); | |
|     glActiveTexture(GL_TEXTURE0); | |
|      | |
|     // Setup orthographic projection matrix | |
|     const float width = ImGui::GetIO().DisplaySize.x; | |
|     const float height = ImGui::GetIO().DisplaySize.y; | |
|     const float ortho_projection[4][4] = | |
|     { | |
|         { 2.0f/width,	0.0f,			0.0f,		0.0f }, | |
|         { 0.0f,			2.0f/-height,	0.0f,		0.0f }, | |
|         { 0.0f,			0.0f,			-1.0f,		0.0f }, | |
|         { -1.0f,		1.0f,			0.0f,		1.0f }, | |
|     }; | |
|     glUseProgram(g_ShaderHandle); | |
|     glUniform1i(g_AttribLocationTex, 0); | |
|     glUniformMatrix4fv(g_AttribLocationProjMtx, 1, GL_FALSE, &ortho_projection[0][0]); | |
|     glBindVertexArray(g_VaoHandle); | |
|      | |
|     for (int n = 0; n < draw_data->CmdListsCount; n++) | |
|     { | |
|         ImDrawList* cmd_list = draw_data->CmdLists[n]; | |
|         ImDrawIdx* idx_buffer = &cmd_list->IdxBuffer.front(); | |
|          | |
|         glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); | |
|         const int needed_vtx_size = cmd_list->VtxBuffer.Size * sizeof(ImDrawVert); | |
|         if (g_VboSize < needed_vtx_size) | |
|         { | |
|             // Grow our buffer if needed | |
|             g_VboSize = needed_vtx_size + 2000 * sizeof(ImDrawVert); | |
|             glBufferData(GL_ARRAY_BUFFER, (GLsizeiptr)g_VboSize, NULL, GL_STREAM_DRAW); | |
|         } | |
| 
 | |
|         unsigned char* vtx_data = (unsigned char*)glMapBufferRange(GL_ARRAY_BUFFER, 0, needed_vtx_size, GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT); | |
|         if (!vtx_data) | |
|             continue; | |
|         memcpy(vtx_data, cmd_list->VtxBuffer.Data, cmd_list->VtxBuffer.Size * sizeof(ImDrawVert)); | |
|         glUnmapBuffer(GL_ARRAY_BUFFER); | |
|          | |
|         for (int cmd_i = 0; cmd_i < cmd_list->CmdBuffer.Size; cmd_i++) | |
|         { | |
|             const ImDrawCmd* pcmd = &cmd_list->CmdBuffer[cmd_i]; | |
|             if (pcmd->UserCallback) | |
|             { | |
|                 pcmd->UserCallback(cmd_list, pcmd); | |
|             } | |
|             else | |
|             { | |
|                 glBindTexture(GL_TEXTURE_2D, (GLuint)(intptr_t)pcmd->TextureId); | |
|                 glScissor((int)(pcmd->ClipRect.x * g_displayScale), | |
|                           (int)((height - pcmd->ClipRect.w) * g_displayScale), | |
|                           (int)((pcmd->ClipRect.z - pcmd->ClipRect.x) * g_displayScale), | |
|                           (int)((pcmd->ClipRect.w - pcmd->ClipRect.y) * g_displayScale)); | |
|                 glDrawElements( GL_TRIANGLES, (GLsizei)pcmd->ElemCount, GL_UNSIGNED_SHORT, idx_buffer ); | |
|             } | |
|             idx_buffer += pcmd->ElemCount; | |
|         } | |
|     } | |
|      | |
|     // Restore modified state | |
|     glBindVertexArray(0); | |
|     glBindBuffer( GL_ARRAY_BUFFER, 0); | |
|     glEnable(GL_CULL_FACE); | |
|     glEnable(GL_DEPTH_TEST); | |
|     glUseProgram(last_program); | |
|     glDisable(GL_SCISSOR_TEST); | |
|     glBindTexture(GL_TEXTURE_2D, last_texture); | |
| } | |
| 
 | |
| void ImGui_ImplIOS_CreateFontsTexture() | |
| { | |
|     // Build texture atlas | |
|     ImGuiIO& io = ImGui::GetIO(); | |
|     unsigned char* pixels; | |
|     int width, height; | |
|     io.Fonts->GetTexDataAsRGBA32(&pixels, &width, &height);   // Load as RGBA 32-bits for OpenGL3 demo because it is more likely to be compatible with user's existing shader. | |
|      | |
|     // Upload texture to graphics system | |
|     GLint last_texture; | |
|     glGetIntegerv(GL_TEXTURE_BINDING_2D, &last_texture); | |
|     glGenTextures(1, &g_FontTexture); | |
|     glBindTexture(GL_TEXTURE_2D, g_FontTexture); | |
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); | |
|     glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); | |
|     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, pixels); | |
|      | |
|     // Store our identifier | |
|     io.Fonts->TexID = (void *)(intptr_t)g_FontTexture; | |
| 
 | |
|     // Restore state | |
|     glBindTexture(GL_TEXTURE_2D, last_texture); | |
| } | |
| 
 | |
| bool ImGui_ImplIOS_CreateDeviceObjects() | |
| { | |
|     const GLchar *vertex_shader = | |
|     "uniform mat4 ProjMtx;\n" | |
|     "attribute highp vec2 Position;\n" | |
|     "attribute highp vec2 UV;\n" | |
|     "attribute highp vec4 Color;\n" | |
|     "varying vec2 Frag_UV;\n" | |
|     "varying vec4 Frag_Color;\n" | |
|     "void main()\n" | |
|     "{\n" | |
|     "	Frag_UV = UV;\n" | |
|     "	Frag_Color = Color;\n" | |
|     "	gl_Position = ProjMtx * vec4(Position.xy,0,1);\n" | |
|     "}\n"; | |
|      | |
|     const GLchar* fragment_shader = | |
|     "uniform sampler2D Texture;\n" | |
|     "varying highp vec2 Frag_UV;\n" | |
|     "varying highp vec4 Frag_Color;\n" | |
|     "void main()\n" | |
|     "{\n" | |
|     "	gl_FragColor = Frag_Color * texture2D( Texture, Frag_UV.st);\n" | |
|     "}\n"; | |
|      | |
|     g_ShaderHandle = glCreateProgram(); | |
|     g_VertHandle = glCreateShader(GL_VERTEX_SHADER); | |
|     g_FragHandle = glCreateShader(GL_FRAGMENT_SHADER); | |
|     glShaderSource(g_VertHandle, 1, &vertex_shader, 0); | |
|     glShaderSource(g_FragHandle, 1, &fragment_shader, 0); | |
|     glCompileShader(g_VertHandle); | |
|      | |
| #if defined(DEBUG) | |
|     GLint logLength; | |
|     glGetShaderiv( g_VertHandle, GL_INFO_LOG_LENGTH, &logLength); | |
|     if (logLength > 0) { | |
|         GLchar *log = (GLchar *)malloc(logLength); | |
|         glGetShaderInfoLog(g_VertHandle, logLength, &logLength, log); | |
|         NSLog(@"VERTEX Shader compile log:\n%s", log); | |
|         free(log); | |
|     } | |
| #endif | |
|      | |
|     glCompileShader(g_FragHandle); | |
|      | |
| #if defined(DEBUG) | |
|     glGetShaderiv( g_FragHandle, GL_INFO_LOG_LENGTH, &logLength); | |
|     if (logLength > 0) { | |
|         GLchar *log = (GLchar *)malloc(logLength); | |
|         glGetShaderInfoLog(g_FragHandle, logLength, &logLength, log); | |
|         NSLog(@"FRAGMENT Shader compile log:\n%s", log); | |
|         free(log); | |
|     } | |
| #endif | |
|      | |
|     glAttachShader(g_ShaderHandle, g_VertHandle); | |
|     glAttachShader(g_ShaderHandle, g_FragHandle); | |
|     glLinkProgram(g_ShaderHandle); | |
|      | |
|     g_AttribLocationTex = glGetUniformLocation(g_ShaderHandle, "Texture"); | |
|     g_AttribLocationProjMtx = glGetUniformLocation(g_ShaderHandle, "ProjMtx"); | |
|     g_AttribLocationPosition = glGetAttribLocation(g_ShaderHandle, "Position"); | |
|     g_AttribLocationUV = glGetAttribLocation(g_ShaderHandle, "UV"); | |
|     g_AttribLocationColor = glGetAttribLocation(g_ShaderHandle, "Color"); | |
|      | |
|     glGenBuffers(1, &g_VboHandle); | |
|      | |
|     glGenVertexArrays(1, &g_VaoHandle); | |
|     glBindVertexArray(g_VaoHandle); | |
|     glBindBuffer(GL_ARRAY_BUFFER, g_VboHandle); | |
|     glEnableVertexAttribArray(g_AttribLocationPosition); | |
|     glEnableVertexAttribArray(g_AttribLocationUV); | |
|     glEnableVertexAttribArray(g_AttribLocationColor); | |
|      | |
|     glVertexAttribPointer(g_AttribLocationPosition, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, pos)); | |
|     glVertexAttribPointer(g_AttribLocationUV, 2, GL_FLOAT, GL_FALSE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, uv)); | |
|     glVertexAttribPointer(g_AttribLocationColor, 4, GL_UNSIGNED_BYTE, GL_TRUE, sizeof(ImDrawVert), (GLvoid*)IM_OFFSETOF(ImDrawVert, col)); | |
| 
 | |
|     glBindVertexArray(0); | |
|     glBindBuffer(GL_ARRAY_BUFFER, 0); | |
|      | |
|     ImGui_ImplIOS_CreateFontsTexture(); | |
|      | |
|     return true; | |
| }
 | |
| 
 |