comparison ios/dw.m @ 2583:1d2f5c4eccc5

iOS: Implement keyboard handling for iOS 13.4 and later. Remove mouse and flipped coordinate system code lingering from MacOS.
author bsmith@81767d24-ef19-dc11-ae90-00e081727c95
date Sun, 23 May 2021 09:43:04 +0000
parents 6fdab466d7a2
children 2acc7ba5dea0
comparison
equal deleted inserted replaced
2582:01fca1937806 2583:1d2f5c4eccc5
331 { 17, DW_SIGNAL_COLUMN_CLICK }, 331 { 17, DW_SIGNAL_COLUMN_CLICK },
332 { 18, DW_SIGNAL_HTML_RESULT }, 332 { 18, DW_SIGNAL_HTML_RESULT },
333 { 19, DW_SIGNAL_HTML_CHANGED } 333 { 19, DW_SIGNAL_HTML_CHANGED }
334 }; 334 };
335 335
336 int _dw_event_handler1(id object, UIEvent *event, int message) 336 int _dw_event_handler1(id object, id event, int message)
337 { 337 {
338 SignalHandler *handler = _dw_get_handler(object, message); 338 SignalHandler *handler = _dw_get_handler(object, message);
339 /* NSLog(@"Event handler - type %d\n", message); */ 339 /* NSLog(@"Event handler - type %d\n", message); */
340 340
341 if(handler) 341 if(handler)
375 return 0; 375 return 0;
376 } 376 }
377 case 2: 377 case 2:
378 { 378 {
379 int (*keypressfunc)(HWND, char, int, int, void *, char *) = handler->signalfunction; 379 int (*keypressfunc)(HWND, char, int, int, void *, char *) = handler->signalfunction;
380 NSString *nchar = @""; /* [event charactersIgnoringModifiers]; */ 380 int special = 0;
381 NSString *nchar = @"";
382 if (@available(iOS 13.4, *)) {
383 UIKey *key = event;
384
385 nchar = [key charactersIgnoringModifiers];
386 special = (int)[key modifierFlags];
387 } else {
388 // Probably won't even get here if not 13.4
389 }
381 unichar vk = [nchar characterAtIndex:0]; 390 unichar vk = [nchar characterAtIndex:0];
382 char *utf8 = NULL, ch = '\0'; 391 char *utf8 = NULL, ch = '\0';
383 int special = 0;
384
385 if(@available(iOS 13.4, *))
386 {
387 special = (int)[event modifierFlags];
388 }
389 392
390 /* Handle a valid key */ 393 /* Handle a valid key */
391 if([nchar length] == 1) 394 if([nchar length] == 1)
392 { 395 {
393 char *tmp = (char *)[nchar UTF8String]; 396 char *tmp = (char *)[nchar UTF8String];
422 } 425 }
423 426
424 return buttonfunc(object, (int)p.x, (int)p.y, button, handler->data); 427 return buttonfunc(object, (int)p.x, (int)p.y, button, handler->data);
425 } 428 }
426 /* Motion notify event */ 429 /* Motion notify event */
427 #if 0 /* Not sure if motion notify applies */
428 case 5: 430 case 5:
429 { 431 {
432 #if 0 /* TODO: See if this can be replicated with gestures/swipes */
430 int (* API motionfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))handler->signalfunction; 433 int (* API motionfunc)(HWND, int, int, int, void *) = (int (* API)(HWND, int, int, int, void *))handler->signalfunction;
431 434
432 return motionfunc(object, (int)p.x, (int)p.y, (int)buttonmask, handler->data); 435 return motionfunc(object, (int)p.x, (int)p.y, (int)buttonmask, handler->data);
436 #endif
437 return -1;
433 } 438 }
434 #endif
435 /* Window close event */ 439 /* Window close event */
436 case 6: 440 case 6:
437 { 441 {
438 int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction; 442 int (* API closefunc)(HWND, void *) = (int (* API)(HWND, void *))handler->signalfunction;
439 return closefunc(object, handler->data); 443 return closefunc(object, handler->data);
558 } 562 }
559 return -1; 563 return -1;
560 } 564 }
561 565
562 /* Sub function to handle redraws */ 566 /* Sub function to handle redraws */
563 int _dw_event_handler(id object, UIEvent *event, int message) 567 int _dw_event_handler(id object, id event, int message)
564 { 568 {
565 int ret = _dw_event_handler1(object, event, message); 569 int ret = _dw_event_handler1(object, event, message);
566 if(ret != -1) 570 if(ret != -1)
567 _dw_redraw(nil, FALSE); 571 _dw_redraw(nil, FALSE);
568 return ret; 572 return ret;
687 UIColor *bgcolor; 691 UIColor *bgcolor;
688 } 692 }
689 -(id)init; 693 -(id)init;
690 -(void)dealloc; 694 -(void)dealloc;
691 -(Box *)box; 695 -(Box *)box;
692 -(id)contentView;
693 -(void *)userdata; 696 -(void *)userdata;
694 -(void)setUserdata:(void *)input; 697 -(void)setUserdata:(void *)input;
695 -(void)drawRect:(CGRect)rect; 698 -(void)drawRect:(CGRect)rect;
696 -(BOOL)isFlipped; 699 -(void)keyDown:(UIKey *)key API_AVAILABLE(ios(13.4));
697 -(void)mouseDown:(UIEvent *)theEvent;
698 -(void)mouseUp:(UIEvent *)theEvent;
699 -(DWMenu *)menuForEvent:(UIEvent *)theEvent;
700 -(void)rightMouseUp:(UIEvent *)theEvent;
701 -(void)otherMouseDown:(UIEvent *)theEvent;
702 -(void)otherMouseUp:(UIEvent *)theEvent;
703 -(void)keyDown:(UIEvent *)theEvent;
704 -(void)setColor:(unsigned long)input; 700 -(void)setColor:(unsigned long)input;
705 -(void)layoutSubviews;
706 @end 701 @end
707 702
708 @implementation DWBox 703 @implementation DWBox
709 -(id)init 704 -(id)init
710 { 705 {
728 _dw_remove_userdata(&root, NULL, TRUE); 723 _dw_remove_userdata(&root, NULL, TRUE);
729 dw_signal_disconnect_by_window(self); 724 dw_signal_disconnect_by_window(self);
730 [super dealloc]; 725 [super dealloc];
731 } 726 }
732 -(Box *)box { return box; } 727 -(Box *)box { return box; }
733 -(id)contentView { return self; }
734 -(void *)userdata { return userdata; } 728 -(void *)userdata { return userdata; }
735 -(void)setUserdata:(void *)input { userdata = input; } 729 -(void)setUserdata:(void *)input { userdata = input; }
736 -(void)drawRect:(CGRect)rect 730 -(void)drawRect:(CGRect)rect
737 { 731 {
738 if(bgcolor) 732 if(bgcolor)
739 { 733 {
740 [bgcolor set]; 734 [bgcolor set];
741 UIRectFill([self bounds]); 735 UIRectFill([self bounds]);
742 } 736 }
743 } 737 }
744 -(BOOL)isFlipped { return YES; } 738 -(void)keyDown:(UIKey *)key API_AVAILABLE(ios(13.4)){ _dw_event_handler(self, key, 2); }
745 -(void)mouseDown:(UIEvent *)theEvent { _dw_event_handler(self, (void *)1, 3); }
746 -(void)mouseUp:(UIEvent *)theEvent { _dw_event_handler(self, (void *)1, 4); }
747 -(DWMenu *)menuForEvent:(UIEvent *)theEvent { _dw_event_handler(self, (void *)2, 3); return nil; }
748 -(void)rightMouseUp:(UIEvent *)theEvent { _dw_event_handler(self, (void *)2, 4); }
749 -(void)otherMouseDown:(UIEvent *)theEvent { _dw_event_handler(self, (void *)3, 3); }
750 -(void)otherMouseUp:(UIEvent *)theEvent { _dw_event_handler(self, (void *)3, 4); }
751 -(void)keyDown:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 2); }
752 -(void)setColor:(unsigned long)input 739 -(void)setColor:(unsigned long)input
753 { 740 {
754 id orig = bgcolor; 741 id orig = bgcolor;
755 742
756 if(input == _dw_colors[DW_CLR_DEFAULT]) 743 if(input == _dw_colors[DW_CLR_DEFAULT])
767 } 754 }
768 } 755 }
769 [self setNeedsDisplay]; 756 [self setNeedsDisplay];
770 [orig release]; 757 [orig release];
771 } 758 }
772 -(void)layoutSubviews { };
773 @end 759 @end
774 760
775 @interface DWWindow : UIWindow 761 @interface DWWindow : UIWindow
776 { 762 {
777 DWMenu *windowmenu, *popupmenu; 763 DWMenu *windowmenu, *popupmenu;
778 int redraw; 764 int redraw;
779 int shown; 765 int shown;
780 } 766 }
781 -(void)sendEvent:(UIEvent *)theEvent; 767 -(void)sendEvent:(UIEvent *)theEvent;
782 -(void)keyDown:(UIEvent *)theEvent; 768 -(void)keyDown:(UIKey *)key API_AVAILABLE(ios(13.4));
783 -(void)mouseDragged:(UIEvent *)theEvent;
784 -(int)redraw; 769 -(int)redraw;
785 -(void)setRedraw:(int)val; 770 -(void)setRedraw:(int)val;
786 -(int)shown; 771 -(int)shown;
787 -(void)setShown:(int)val; 772 -(void)setShown:(int)val;
788 -(void)layoutSubviews; 773 -(void)layoutSubviews;
801 rcode = _dw_event_handler(self, theEvent, 2); 786 rcode = _dw_event_handler(self, theEvent, 2);
802 } 787 }
803 if ( rcode != TRUE ) 788 if ( rcode != TRUE )
804 [super sendEvent:theEvent]; 789 [super sendEvent:theEvent];
805 } 790 }
806 -(void)keyDown:(UIEvent *)theEvent { } 791 -(void)keyDown:(UIKey *)key { }
807 -(void)mouseDragged:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 5); }
808 -(int)redraw { return redraw; } 792 -(int)redraw { return redraw; }
809 -(void)setRedraw:(int)val { redraw = val; } 793 -(void)setRedraw:(int)val { redraw = val; }
810 -(int)shown { return shown; } 794 -(int)shown { return shown; }
811 -(void)setShown:(int)val { shown = val; } 795 -(void)setShown:(int)val { shown = val; }
812 -(void)layoutSubviews { } 796 -(void)layoutSubviews { }
852 -(void)setFont:(UIFont *)input; 836 -(void)setFont:(UIFont *)input;
853 -(UIFont *)font; 837 -(UIFont *)font;
854 -(void)setSize:(CGSize)input; 838 -(void)setSize:(CGSize)input;
855 -(CGSize)size; 839 -(CGSize)size;
856 -(DWImage *)cachedImage; 840 -(DWImage *)cachedImage;
857 -(void)mouseDown:(UIEvent *)theEvent; 841 -(void)keyDown:(UIKey *)key API_AVAILABLE(ios(13.4));
858 -(void)mouseUp:(UIEvent *)theEvent;
859 -(DWMenu *)menuForEvent:(UIEvent *)theEvent;
860 -(void)rightMouseUp:(UIEvent *)theEvent;
861 -(void)otherMouseDown:(UIEvent *)theEvent;
862 -(void)otherMouseUp:(UIEvent *)theEvent;
863 -(void)drawRect:(CGRect)rect;
864 -(void)keyDown:(UIEvent *)theEvent;
865 -(BOOL)isFlipped;
866 @end 842 @end
867 843
868 @implementation DWRender 844 @implementation DWRender
869 -(void *)userdata { return userdata; } 845 -(void *)userdata { return userdata; }
870 -(void)setUserdata:(void *)input { userdata = input; } 846 -(void)setUserdata:(void *)input { userdata = input; }
900 /* Mark this render dirty if something is requesting it to draw */ 876 /* Mark this render dirty if something is requesting it to draw */
901 if(![_DWDirtyDrawables containsObject:self]) 877 if(![_DWDirtyDrawables containsObject:self])
902 [_DWDirtyDrawables addObject:self]; 878 [_DWDirtyDrawables addObject:self];
903 return cachedImage; 879 return cachedImage;
904 } 880 }
905 -(void)mouseDown:(UIEvent *)theEvent
906 {
907 if(![theEvent isMemberOfClass:[UIEvent class]])
908 _dw_event_handler(self, theEvent, 3);
909 }
910 -(void)mouseUp:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 4); }
911 -(DWMenu *)menuForEvent:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 3); return nil; }
912 -(void)rightMouseUp:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 4); }
913 -(void)otherMouseDown:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 3); }
914 -(void)otherMouseUp:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 4); }
915 -(void)mouseDragged:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 5); }
916 -(void)drawRect:(CGRect)rect { 881 -(void)drawRect:(CGRect)rect {
917 _dw_event_handler(self, nil, 7); 882 _dw_event_handler(self, nil, 7);
918 if(cachedImage) 883 if(cachedImage)
919 { 884 {
920 [[cachedImage image] drawInRect:self.bounds]; 885 [[cachedImage image] drawInRect:self.bounds];
921 [_DWDirtyDrawables removeObject:self]; 886 [_DWDirtyDrawables removeObject:self];
922 [self setNeedsDisplay]; 887 [self setNeedsDisplay];
923 } 888 }
924 } 889 }
925 -(void)keyDown:(UIEvent *)theEvent { _dw_event_handler(self, theEvent, 2); } 890 -(void)keyDown:(UIKey *)key API_AVAILABLE(ios(13.4)){ _dw_event_handler(self, key, 2); }
926 -(BOOL)isFlipped { return YES; }
927 -(void)dealloc { 891 -(void)dealloc {
928 UserData *root = userdata; 892 UserData *root = userdata;
929 _dw_remove_userdata(&root, NULL, TRUE); 893 _dw_remove_userdata(&root, NULL, TRUE);
930 [font release]; 894 [font release];
931 dw_signal_disconnect_by_window(self); 895 dw_signal_disconnect_by_window(self);
1332 -(void *)userdata { return userdata; } 1296 -(void *)userdata { return userdata; }
1333 -(void)setUserdata:(void *)input { userdata = input; } 1297 -(void)setUserdata:(void *)input { userdata = input; }
1334 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation 1298 -(void)webView:(WKWebView *)webView didCommitNavigation:(WKNavigation *)navigation
1335 { 1299 {
1336 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_STARTED), [[self URL] absoluteString] }; 1300 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_STARTED), [[self URL] absoluteString] };
1337 _dw_event_handler(self, (UIEvent *)params, 19); 1301 _dw_event_handler(self, (id)params, 19);
1338 } 1302 }
1339 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation 1303 -(void)webView:(WKWebView *)webView didFinishNavigation:(WKNavigation *)navigation
1340 { 1304 {
1341 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_COMPLETE), [[self URL] absoluteString] }; 1305 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_COMPLETE), [[self URL] absoluteString] };
1342 _dw_event_handler(self, (UIEvent *)params, 19); 1306 _dw_event_handler(self, (id)params, 19);
1343 } 1307 }
1344 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation 1308 -(void)webView:(WKWebView *)webView didStartProvisionalNavigation:(WKNavigation *)navigation
1345 { 1309 {
1346 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_LOADING), [[self URL] absoluteString] }; 1310 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_LOADING), [[self URL] absoluteString] };
1347 _dw_event_handler(self, (UIEvent *)params, 19); 1311 _dw_event_handler(self, (id)params, 19);
1348 } 1312 }
1349 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation 1313 -(void)webView:(WKWebView *)webView didReceiveServerRedirectForProvisionalNavigation:(WKNavigation *)navigation
1350 { 1314 {
1351 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_REDIRECT), [[self URL] absoluteString] }; 1315 void *params[2] = { DW_INT_TO_POINTER(DW_HTML_CHANGE_REDIRECT), [[self URL] absoluteString] };
1352 _dw_event_handler(self, (UIEvent *)params, 19); 1316 _dw_event_handler(self, (id)params, 19);
1353 } 1317 }
1354 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; } 1318 -(void)dealloc { UserData *root = userdata; _dw_remove_userdata(&root, NULL, TRUE); dw_signal_disconnect_by_window(self); [super dealloc]; }
1355 @end 1319 @end
1356 1320
1357 /* Subclass for a top-level window */ 1321 /* Subclass for a top-level window */
2151 params[0] = [self getRowTitle:(int)indexPath.row]; 2115 params[0] = [self getRowTitle:(int)indexPath.row];
2152 params[1] = [self getRowData:(int)indexPath.row]; 2116 params[1] = [self getRowData:(int)indexPath.row];
2153 params[2] = DW_INT_TO_POINTER((int)point.x); 2117 params[2] = DW_INT_TO_POINTER((int)point.x);
2154 params[3] = DW_INT_TO_POINTER((int)point.y); 2118 params[3] = DW_INT_TO_POINTER((int)point.y);
2155 2119
2156 _dw_event_handler(self, (UIEvent *)params, 10); 2120 _dw_event_handler(self, (id)params, 10);
2157 2121
2158 if(window) 2122 if(window)
2159 { 2123 {
2160 __block UIMenu *popupmenu = [[window popupMenu] menu]; 2124 __block UIMenu *popupmenu = [[window popupMenu] menu];
2161 config = [UIContextMenuConfiguration configurationWithIdentifier:@"DWContextMenu" 2125 config = [UIContextMenuConfiguration configurationWithIdentifier:@"DWContextMenu"
2418 2382
2419 /* If multiple selection is enabled, treat it as selectionChanged: */ 2383 /* If multiple selection is enabled, treat it as selectionChanged: */
2420 if([self allowsMultipleSelection]) 2384 if([self allowsMultipleSelection])
2421 { 2385 {
2422 /* Handler for container class */ 2386 /* Handler for container class */
2423 _dw_event_handler(self, (UIEvent *)params, 12); 2387 _dw_event_handler(self, (id)params, 12);
2424 /* Handler for listbox class */ 2388 /* Handler for listbox class */
2425 _dw_event_handler(self, DW_INT_TO_POINTER((int)indexPath.row), 11); 2389 _dw_event_handler(self, DW_INT_TO_POINTER((int)indexPath.row), 11);
2426 } 2390 }
2427 else /* Otherwise treat it as doubleClicked: */ 2391 else /* Otherwise treat it as doubleClicked: */
2428 { 2392 {
2429 /* Handler for container class */ 2393 /* Handler for container class */
2430 _dw_event_handler(self, (UIEvent *)params, 9); 2394 _dw_event_handler(self, (id)params, 9);
2431 } 2395 }
2432 } 2396 }
2433 -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath 2397 -(void)tableView:(UITableView *)tableView didDeselectRowAtIndexPath:(NSIndexPath *)indexPath
2434 { 2398 {
2435 if([self allowsMultipleSelection]) 2399 if([self allowsMultipleSelection])
7350 DW_FUNCTION_ADD_PARAM1(cid) 7314 DW_FUNCTION_ADD_PARAM1(cid)
7351 DW_FUNCTION_RETURN(dw_calendar_new, HWND) 7315 DW_FUNCTION_RETURN(dw_calendar_new, HWND)
7352 DW_FUNCTION_RESTORE_PARAM1(cid, ULONG) 7316 DW_FUNCTION_RESTORE_PARAM1(cid, ULONG)
7353 { 7317 {
7354 DWCalendar *calendar = nil; 7318 DWCalendar *calendar = nil;
7355 #if 0 /* TODO: Figure out why this hangs the UI */ 7319 #if 0 /* TODO: Figure out why this corrupts DWBoxes in its hierarchy */
7356 DWCalendar *calendar = [[[DWCalendar alloc] init] retain]; 7320 DWCalendar *calendar = [[[DWCalendar alloc] init] retain];
7321 if (@available(iOS 14.0, *)) {
7322 [calendar setPreferredDatePickerStyle:UIDatePickerStyleInline];
7323 } else {
7324 // We really want the iOS 14 style to match the other platforms...
7325 // but just leave it the default spinner style on 13 and earlier.
7326 }
7357 [calendar setDatePickerMode:UIDatePickerModeDate]; 7327 [calendar setDatePickerMode:UIDatePickerModeDate];
7328 [calendar setDate:[NSDate date]];
7358 [calendar setTag:cid]; 7329 [calendar setTag:cid];
7359 [calendar setDate:[NSDate date]];
7360 #endif 7330 #endif
7361 DW_FUNCTION_RETURN_THIS(calendar); 7331 DW_FUNCTION_RETURN_THIS(calendar);
7362 } 7332 }
7363 7333
7364 /* 7334 /*
7505 DW_LOCAL_POOL_IN; 7475 DW_LOCAL_POOL_IN;
7506 7476
7507 [html evaluateJavaScript:[NSString stringWithUTF8String:script] completionHandler:^(NSString *result, NSError *error) 7477 [html evaluateJavaScript:[NSString stringWithUTF8String:script] completionHandler:^(NSString *result, NSError *error)
7508 { 7478 {
7509 void *params[2] = { result, scriptdata }; 7479 void *params[2] = { result, scriptdata };
7510 _dw_event_handler(html, (UIEvent *)params, 18); 7480 _dw_event_handler(html, (id)params, 18);
7511 }]; 7481 }];
7512 DW_LOCAL_POOL_OUT; 7482 DW_LOCAL_POOL_OUT;
7513 DW_FUNCTION_RETURN_THIS(retval); 7483 DW_FUNCTION_RETURN_THIS(retval);
7514 } 7484 }
7515 7485
7612 { 7582 {
7613 DWMenu *thismenu = (DWMenu *)*menu; 7583 DWMenu *thismenu = (DWMenu *)*menu;
7614 id object = parent; 7584 id object = parent;
7615 DWWindow *window = [object isMemberOfClass:[DWWindow class]] ? object : (DWWindow *)[object window]; 7585 DWWindow *window = [object isMemberOfClass:[DWWindow class]] ? object : (DWWindow *)[object window];
7616 [thismenu autorelease]; 7586 [thismenu autorelease];
7617 [window setPopupMenu:[thismenu menu]]; 7587 [window setPopupMenu:thismenu];
7618 *menu = nil; 7588 *menu = nil;
7619 } 7589 }
7620 7590
7621 char _dw_removetilde(char *dest, const char *src) 7591 char _dw_removetilde(char *dest, const char *src)
7622 { 7592 {