=> e48a9a27bd11dbef9531bd12d3c0c60cc771b2c3
[1mdiff --git a/sdl2-macos-ios.diff b/sdl2-macos-ios.diff[m [1mindex 04d0f2e5..ecb23824 100644[m [1m--- a/sdl2-macos-ios.diff[m [1m+++ b/sdl2-macos-ios.diff[m [36m@@ -1,8 +1,8 @@[m [31m-Only in SDL2-2.0.14/src: .DS_Store[m [31m-diff -ru SDL2-2.0.14-original/src/events/SDL_mouse.c SDL2-2.0.14/src/events/SDL_mouse.c[m [31m---- SDL2-2.0.14-original/src/events/SDL_mouse.c 2020-12-21 19:44:36.000000000 +0200[m [31m-+++ SDL2-2.0.14/src/events/SDL_mouse.c 2021-01-06 18:31:18.000000000 +0200[m [31m-@@ -647,8 +647,8 @@[m [32m+[m[32mdiff --git a/src/events/SDL_mouse.c b/src/events/SDL_mouse.c[m [32m+[m[32mindex a776bcca8..2d5e685e3 100644[m [32m+[m[32m--- a/src/events/SDL_mouse.c[m [32m+[m[32m+++ b/src/events/SDL_mouse.c[m [32m+[m[32m@@ -647,8 +647,8 @@ SDL_SendMouseWheel(SDL_Window * window, SDL_MouseID mouseID, float x, float y, S[m event.wheel.preciseX = x;[m event.wheel.preciseY = y;[m #endif[m [36m@@ -13,11 +13,11 @@[m [mdiff -ru SDL2-2.0.14-original/src/events/SDL_mouse.c SDL2-2.0.14/src/events/SDL_[m event.wheel.direction = (Uint32)direction;[m posted = (SDL_PushEvent(&event) > 0);[m }[m [31m-Only in SDL2-2.0.14/src/video: .DS_Store[m [31m-diff -ru SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m SDL2-2.0.14/src/video/cocoa/SDL_cocoamouse.m[m [31m---- SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m 2020-12-21 19:44:36.000000000 +0200[m [31m-+++ SDL2-2.0.14/src/video/cocoa/SDL_cocoamouse.m 2021-01-06 18:31:18.000000000 +0200[m [31m-@@ -423,10 +423,16 @@[m [32m+[m[32mdiff --git a/src/video/cocoa/SDL_cocoamouse.m b/src/video/cocoa/SDL_cocoamouse.m[m [32m+[m[32mindex e9d832d64..4cfa3624b 100644[m [32m+[m[32m--- a/src/video/cocoa/SDL_cocoamouse.m[m [32m+[m[32m+++ b/src/video/cocoa/SDL_cocoamouse.m[m [32m+[m[32m@@ -463,10 +463,16 @@ + (NSCursor *)invisibleCursor[m }[m [m SDL_MouseID mouseID = mouse->mouseID;[m [36m@@ -36,10 +36,41 @@[m [mdiff -ru SDL2-2.0.14-original/src/video/cocoa/SDL_cocoamouse.m SDL2-2.0.14/src/v[m if ([event respondsToSelector:@selector(isDirectionInvertedFromDevice)]) {[m if ([event isDirectionInvertedFromDevice] == YES) {[m direction = SDL_MOUSEWHEEL_FLIPPED;[m [31m-Only in SDL2-2.0.14/src/video/cocoa: SDL_cocoamouse.m.orig[m [31m-diff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.h[m [31m---- SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h 2020-12-21 19:44:36.000000000 +0200[m [31m-+++ SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.h 2021-05-17 13:11:13.000000000 +0300[m [32m+[m[32mdiff --git a/src/video/cocoa/SDL_cocoawindow.h b/src/video/cocoa/SDL_cocoawindow.h[m [32m+[m[32mindex 37bec665e..5e3a3995f 100644[m [32m+[m[32m--- a/src/video/cocoa/SDL_cocoawindow.h[m [32m+[m[32m+++ b/src/video/cocoa/SDL_cocoawindow.h[m [32m+[m[32m@@ -109,6 +109,8 @@ typedef enum[m [32m+[m[32m /* Touch event handling */[m [32m+[m[32m -(void) handleTouches:(NSTouchPhase) phase withEvent:(NSEvent*) theEvent;[m [32m+[m[41m [m [32m+[m[32m+-(void) syncMouseButtonState;[m [32m+[m[32m+[m [32m+[m[32m @end[m [32m+[m[32m /* *INDENT-ON* */[m [32m+[m[41m [m [32m+[m[32mdiff --git a/src/video/cocoa/SDL_cocoawindow.m b/src/video/cocoa/SDL_cocoawindow.m[m [32m+[m[32mindex 7a1446f09..86db35600 100644[m [32m+[m[32m--- a/src/video/cocoa/SDL_cocoawindow.m[m [32m+[m[32m+++ b/src/video/cocoa/SDL_cocoawindow.m[m [32m+[m[32m@@ -1073,6 +1073,13 @@ - (void)otherMouseDown:(NSEvent *)theEvent[m [32m+[m[32m [self mouseDown:theEvent];[m [32m+[m[32m }[m [32m+[m[41m [m [32m+[m[32m+- (void)syncMouseButtonState {[m [32m+[m[32m+ SDL_Mouse *mouse = SDL_GetMouse();[m [32m+[m[32m+ if (mouse) {[m [32m+[m[32m+ mouse->buttonstate = SDL_GetGlobalMouseState(NULL, NULL);[m [32m+[m[32m+ }[m [32m+[m[32m+}[m [32m+[m[32m+[m [32m+[m[32m - (void)mouseUp:(NSEvent *)theEvent[m [32m+[m[32m {[m [32m+[m[32m const SDL_Mouse *mouse = SDL_GetMouse();[m [32m+[m[32mdiff --git a/src/video/uikit/SDL_uikitviewcontroller.h b/src/video/uikit/SDL_uikitviewcontroller.h[m [32m+[m[32mindex f7f4c9de6..50c72aad0 100644[m [32m+[m[32m--- a/src/video/uikit/SDL_uikitviewcontroller.h[m [32m+[m[32m+++ b/src/video/uikit/SDL_uikitviewcontroller.h[m @@ -58,10 +58,13 @@[m #if !TARGET_OS_TV[m - (NSUInteger)supportedInterfaceOrientations;[m [36m@@ -54,10 +85,11 @@[m [mdiff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.h SDL2-2.0[m #endif[m [m #if SDL_IPHONE_KEYBOARD[m [31m-diff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.m[m [31m---- SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m 2020-12-21 19:44:36.000000000 +0200[m [31m-+++ SDL2-2.0.14/src/video/uikit/SDL_uikitviewcontroller.m 2021-05-17 13:11:58.000000000 +0300[m [31m-@@ -104,6 +104,7 @@[m [32m+[m[32mdiff --git a/src/video/uikit/SDL_uikitviewcontroller.m b/src/video/uikit/SDL_uikitviewcontroller.m[m [32m+[m[32mindex c51d1aed2..cd8db9517 100644[m [32m+[m[32m--- a/src/video/uikit/SDL_uikitviewcontroller.m[m [32m+[m[32m+++ b/src/video/uikit/SDL_uikitviewcontroller.m[m [32m+[m[32m@@ -105,6 +105,7 @@ - (instancetype)initWithSDLWindow:(SDL_Window *)_window[m #endif[m [m #if !TARGET_OS_TV[m [36m@@ -65,7 +97,7 @@[m [mdiff -ru SDL2-2.0.14-original/src/video/uikit/SDL_uikitviewcontroller.m SDL2-2.0[m SDL_AddHintCallback(SDL_HINT_IOS_HIDE_HOME_INDICATOR,[m SDL_HideHomeIndicatorHintChanged,[m (__bridge void *) self);[m [31m-@@ -229,6 +230,17 @@[m [32m+[m[32m@@ -230,6 +231,17 @@ - (BOOL)prefersHomeIndicatorAutoHidden[m return hidden;[m }[m [m [1mdiff --git a/src/app.h b/src/app.h[m [1mindex 8966e8c7..0dff939f 100644[m [1m--- a/src/app.h[m [1m+++ b/src/app.h[m [36m@@ -129,7 +129,7 @@[m [miLocalDef void postCommandString_Root(iRoot *d, const iString *command) {[m }[m }[m iLocalDef void postCommand_App(const char *command) {[m [31m- postCommandf_App(command);[m [32m+[m[32m postCommand_Root(NULL, command);[m }[m [m iDocumentWidget * document_Command (const char *cmd);[m [1mdiff --git a/src/macos.h b/src/macos.h[m [1mindex 20b95943..22a6dfff 100644[m [1m--- a/src/macos.h[m [1m+++ b/src/macos.h[m [36m@@ -24,7 +24,9 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m [m #include "ui/util.h"[m [m [32m+[m[32miDeclareType(MenuItem)[m iDeclareType(Window)[m [32m+[m[32miDeclareType(Widget)[m [m /* Platform-specific functionality for macOS */[m [m [36m@@ -40,3 +42,5 @@[m [mvoid enableMenu_MacOS (const char *menuLabel, iBool enable);[m void enableMenuItem_MacOS (const char *menuItemCommand, iBool enable);[m void enableMenuItemsByKey_MacOS (int key, int kmods, iBool enable);[m void handleCommand_MacOS (const char *cmd);[m [32m+[m [32m+[m[32mvoid showPopupMenu_MacOS (iWidget *source, iInt2 windowCoord, const iMenuItem *items, size_t n);[m [1mdiff --git a/src/macos.m b/src/macos.m[m [1mindex 298db0f8..cec53a7d 100644[m [1m--- a/src/macos.m[m [1m+++ b/src/macos.m[m [36m@@ -77,6 +77,14 @@[m [miBool shouldDefaultToMetalRenderer_MacOS(void) {[m return ver.x > 10 || ver.y > 13;*/[m }[m [m [32m+[m[32mstatic void ignoreImmediateKeyDownEvents_(void) {[m [32m+[m[32m /* SDL ignores menu key equivalents so the keydown events will be posted regardless.[m [32m+[m[32m However, we shouldn't double-activate menu items when a shortcut key is used in our[m [32m+[m[32m widgets. Quite a kludge: take advantage of Window's focus-acquisition threshold to[m [32m+[m[32m ignore the immediately following key down events. */[m [32m+[m[32m get_Window()->focusGainedAt = SDL_GetTicks();[m [32m+[m[32m}[m [32m+[m /*----------------------------------------------------------------------------------------------*/[m [m @interface CommandButton : NSCustomTouchBarItem {[m [36m@@ -146,11 +154,60 @@[m [miBool shouldDefaultToMetalRenderer_MacOS(void) {[m [m /*----------------------------------------------------------------------------------------------*/[m [m [32m+[m[32m@interface MenuCommands : NSObject {[m [32m+[m[32m NSMutableDictionary*commands;[m [32m+[m[32m iWidget *source;[m [32m+[m[32m}[m [32m+[m[32m@end[m [32m+[m [32m+[m[32m@implementation MenuCommands[m [32m+[m [32m+[m[32m- (id)init {[m [32m+[m[32m commands = [[NSMutableDictionary alloc] init];[m [32m+[m[32m source = NULL;[m [32m+[m[32m return self;[m [32m+[m[32m}[m [32m+[m [32m+[m[32m- (void)setCommand:(NSString *)command forMenuItem:(NSMenuItem *)menuItem {[m [32m+[m[32m [commands setObject:command forKey:[menuItem title]];[m [32m+[m[32m}[m [32m+[m [32m+[m[32m- (void)setSource:(iWidget *)widget {[m [32m+[m[32m source = widget;[m [32m+[m[32m}[m [32m+[m [32m+[m[32m- (void)clear {[m [32m+[m[32m [commands removeAllObjects];[m [32m+[m[32m}[m [32m+[m [32m+[m[32m- (NSString *)commandForMenuItem:(NSMenuItem *)menuItem {[m [32m+[m[32m return [commands objectForKey:[menuItem title]];[m [32m+[m[32m}[m [32m+[m [32m+[m[32m- (void)postMenuItemCommand:(id)sender {[m [32m+[m[32m NSString *command = [commands objectForKey:[(NSMenuItem *)sender title]];[m [32m+[m[32m if (command) {[m [32m+[m[32m const char *cstr = [command cStringUsingEncoding:NSUTF8StringEncoding];[m [32m+[m[32m if (source) {[m [32m+[m[32m postCommand_Widget(source, "%s", cstr);[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m postCommand_Root(NULL, cstr);[m [32m+[m[32m }[m [32m+[m[32m ignoreImmediateKeyDownEvents_();[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32m@end[m [32m+[m [32m+[m[32m/*----------------------------------------------------------------------------------------------*/[m [32m+[m @interface MyDelegate : NSResponder {[m enum iTouchBarVariant touchBarVariant;[m NSString *currentAppearanceName;[m NSObject *sdlDelegate;[m [31m- NSMutableDictionary *menuCommands;[m [32m+[m[32m //NSMutableDictionary *menuCommands;[m [32m+[m[32m MenuCommands *menuCommands;[m }[m - (id)initWithSDLDelegate:(NSObject *)sdl;[m - (NSTouchBar *)makeTouchBar;[m [36m@@ -165,7 +222,7 @@[m [miBool shouldDefaultToMetalRenderer_MacOS(void) {[m - (id)initWithSDLDelegate:(NSObject *)sdl {[m [super init];[m currentAppearanceName = nil;[m [31m- menuCommands = [[NSMutableDictionary alloc] init];[m [32m+[m[32m menuCommands = [[MenuCommands alloc] init];[m touchBarVariant = default_TouchBarVariant;[m sdlDelegate = sdl;[m return self;[m [36m@@ -182,6 +239,14 @@[m [miBool shouldDefaultToMetalRenderer_MacOS(void) {[m self.touchBar = nil;[m }[m [m [32m+[m[32m- (MenuCommands *)menuCommands {[m [32m+[m[32m return menuCommands;[m [32m+[m[32m}[m [32m+[m [32m+[m[32m- (void)postMenuItemCommand:(id)sender {[m [32m+[m[32m [menuCommands postMenuItemCommand:sender];[m [32m+[m[32m}[m [32m+[m static void appearanceChanged_MacOS_(NSString *name) {[m const iBool isDark = [name containsString:@"Dark"];[m const iBool isHighContrast = [name containsString:@"HighContrast"];[m [36m@@ -198,10 +263,6 @@[m [mstatic void appearanceChanged_MacOS_(NSString *name) {[m }[m }[m [m [31m-- (void)setCommand:(NSString *)command forMenuItem:(NSMenuItem *)menuItem {[m [31m- [menuCommands setObject:command forKey:[menuItem title]];[m [31m-}[m [31m-[m - (BOOL)application:(NSApplication *)app openFile:(NSString *)filename {[m return [sdlDelegate application:app openFile:filename];[m }[m [36m@@ -258,31 +319,11 @@[m [mstatic void appearanceChanged_MacOS_(NSString *name) {[m ignoreImmediateKeyDownEvents_();[m }[m [m [31m-static void ignoreImmediateKeyDownEvents_(void) {[m [31m- /* SDL ignores menu key equivalents so the keydown events will be posted regardless.[m [31m- However, we shouldn't double-activate menu items when a shortcut key is used in our[m [31m- widgets. Quite a kludge: take advantage of Window's focus-acquisition threshold to[m [31m- ignore the immediately following key down events. */[m [31m- get_Window()->focusGainedAt = SDL_GetTicks();[m [31m-}[m [31m-[m - (void)closeTab {[m postCommand_App("tabs.close");[m ignoreImmediateKeyDownEvents_();[m }[m [m [31m-- (NSString *)commandForItem:(NSMenuItem *)menuItem {[m [31m- return [menuCommands objectForKey:[menuItem title]];[m [31m-}[m [31m-[m [31m-- (void)postMenuItemCommand:(id)sender {[m [31m- NSString *command = [menuCommands objectForKey:[(NSMenuItem *)sender title]];[m [31m- if (command) {[m [31m- postCommand_App([command cStringUsingEncoding:NSUTF8StringEncoding]);[m [31m- ignoreImmediateKeyDownEvents_();[m [31m- }[m [31m-}[m [31m-[m - (void)sidebarModePressed:(id)sender {[m NSSegmentedControl *seg = sender;[m postCommandf_App("sidebar.mode arg:%d toggle:1", (int) [seg selectedSegment]);[m [36m@@ -403,7 +444,7 @@[m [mvoid enableMenuItem_MacOS(const char *menuItemCommand, iBool enable) {[m NSMenu *menu = mainMenuItem.submenu;[m if (menu) {[m for (NSMenuItem *menuItem in menu.itemArray) {[m [31m- NSString *command = [myDel commandForItem:menuItem];[m [32m+[m[32m NSString *command = [[myDel menuCommands] commandForMenuItem:menuItem];[m if (command) {[m if (!iCmpStr([command cStringUsingEncoding:NSUTF8StringEncoding],[m menuItemCommand)) {[m [36m@@ -483,18 +524,8 @@[m [mvoid removeMenu_MacOS(int atIndex) {[m [appMenu removeItemAtIndex:atIndex];[m }[m [m [31m-void insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *items, size_t count) {[m [31m- NSApplication *app = [NSApplication sharedApplication];[m [31m- MyDelegate *myDel = (MyDelegate *) app.delegate;[m [31m- NSMenu *appMenu = [app mainMenu];[m [31m- menuLabel = translateCStr_Lang(menuLabel);[m [31m- NSMenuItem *mainItem = [appMenu insertItemWithTitle:[NSString stringWithUTF8String:menuLabel][m [31m- action:nil[m [31m- keyEquivalent:@""[m [31m- atIndex:atIndex];[m [31m- NSMenu *menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:menuLabel]];[m [31m- [menu setAutoenablesItems:NO];[m [31m- for (size_t i = 0; i < count; ++i) {[m [32m+[m[32mstatic void makeMenuItems_(NSMenu *menu, MenuCommands *commands, const iMenuItem *items, size_t n) {[m [32m+[m[32m for (size_t i = 0; i < n && items[i].label; ++i) {[m const char *label = translateCStr_Lang(items[i].label);[m if (label[0] == '\v') {[m /* Skip the formatting escape. */[m [36m@@ -505,13 +536,19 @@[m [mvoid insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *[m }[m else {[m const iBool hasCommand = (items[i].command && items[i].command[0]);[m [31m- NSMenuItem *item = [menu addItemWithTitle:[NSString stringWithUTF8String:label][m [32m+[m[32m iString itemTitle;[m [32m+[m[32m initCStr_String(&itemTitle, label);[m [32m+[m[32m removeIconPrefix_String(&itemTitle);[m [32m+[m[32m NSMenuItem *item = [menu addItemWithTitle:[NSString stringWithUTF8String:cstr_String(&itemTitle)][m action:(hasCommand ? @selector(postMenuItemCommand:) : nil)[m keyEquivalent:@""];[m [32m+[m[32m deinit_String(&itemTitle);[m [32m+[m[32m [item setTarget:commands];[m int key = items[i].key;[m int kmods = items[i].kmods;[m if (hasCommand) {[m [31m- [myDel setCommand:[NSString stringWithUTF8String:items[i].command] forMenuItem:item];[m [32m+[m[32m [commands setCommand:[NSString stringWithUTF8String:items[i].command][m [32m+[m[32m forMenuItem:item];[m /* Bindings may have a different key. */[m const iBinding *bind = findCommand_Keys(items[i].command);[m if (bind && bind->id < builtIn_BindingId) {[m [36m@@ -522,6 +559,20 @@[m [mvoid insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *[m setShortcut_NSMenuItem_(item, key, kmods);[m }[m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mvoid insertMenuItems_MacOS(const char *menuLabel, int atIndex, const iMenuItem *items, size_t count) {[m [32m+[m[32m NSApplication *app = [NSApplication sharedApplication];[m [32m+[m[32m MyDelegate *myDel = (MyDelegate *) app.delegate;[m [32m+[m[32m NSMenu *appMenu = [app mainMenu];[m [32m+[m[32m menuLabel = translateCStr_Lang(menuLabel);[m [32m+[m[32m NSMenuItem *mainItem = [appMenu insertItemWithTitle:[NSString stringWithUTF8String:menuLabel][m [32m+[m[32m action:nil[m [32m+[m[32m keyEquivalent:@""[m [32m+[m[32m atIndex:atIndex];[m [32m+[m[32m NSMenu *menu = [[NSMenu alloc] initWithTitle:[NSString stringWithUTF8String:menuLabel]];[m [32m+[m[32m [menu setAutoenablesItems:NO];[m [32m+[m[32m makeMenuItems_(menu, [myDel menuCommands], items, count);[m [mainItem setSubmenu:menu];[m [menu release];[m }[m [36m@@ -542,7 +593,7 @@[m [mvoid handleCommand_MacOS(const char *cmd) {[m if (menu) {[m int itemIndex = 0;[m for (NSMenuItem *menuItem in menu.itemArray) {[m [31m- NSString *command = [myDel commandForItem:menuItem];[m [32m+[m[32m NSString *command = [[myDel menuCommands] commandForMenuItem:menuItem];[m if (!command && mainIndex == 6 && itemIndex == 0) {[m /* Window > Close */[m command = @"tabs.close";[m [36m@@ -568,3 +619,29 @@[m [mvoid handleCommand_MacOS(const char *cmd) {[m void log_MacOS(const char *msg) {[m NSLog(@"%s", msg);[m }[m [32m+[m [32m+[m[32mvoid showPopupMenu_MacOS(iWidget *source, iInt2 windowCoord, const iMenuItem *items, size_t n) {[m [32m+[m[32m NSMenu * menu = [[NSMenu alloc] init];[m [32m+[m[32m MenuCommands *menuCommands = [[MenuCommands alloc] init];[m [32m+[m[32m iWindow * window = as_Window(mainWindow_App());[m [32m+[m[32m NSWindow * nsWindow = nsWindow_(window->win);[m [32m+[m[32m /* View coordinates are flipped. */[m [32m+[m[32m windowCoord.y = window->size.y - windowCoord.y;[m [32m+[m[32m windowCoord = divf_I2(windowCoord, window->pixelRatio);[m [32m+[m[32m NSPoint screenPoint = [nsWindow convertPointToScreen:(CGPoint){ windowCoord.x, windowCoord.y }];[m [32m+[m[32m makeMenuItems_(menu, menuCommands, items, n);[m [32m+[m[32m [menuCommands setSource:source];[m [32m+[m[32m [menu popUpMenuPositioningItem:nil atLocation:screenPoint inView:nil];[m [32m+[m[32m [menu release];[m [32m+[m[32m [menuCommands release];[m [32m+[m[32m /* The right mouse button has now been released so let SDL know about it. The button up event[m [32m+[m[32m was consumed by the popup menu so it got never passed to SDL. */[m [32m+[m[32m SEL sel = NSSelectorFromString(@"syncMouseButtonState"); /* custom method */[m [32m+[m[32m if ([[nsWindow delegate] respondsToSelector:sel]) {[m [32m+[m[32m NSInvocation *call = [NSInvocation invocationWithMethodSignature:[m [32m+[m[32m [NSMethodSignature signatureWithObjCTypes:"v@:"]];[m [32m+[m[32m [call setSelector:sel];[m [32m+[m[32m [call invokeWithTarget:[nsWindow delegate]];[m [32m+[m[32m }[m [32m+[m[32m}[m [41m+[m [1mdiff --git a/src/ui/inputwidget.c b/src/ui/inputwidget.c[m [1mindex f02bf408..37d655b7 100644[m [1m--- a/src/ui/inputwidget.c[m [1m+++ b/src/ui/inputwidget.c[m [36m@@ -2365,8 +2365,8 @@[m [mstatic void draw_InputWidget_(const iInputWidget *d) {[m cursorChar.start = charPos_InputWidget_(d, d->cursor);[m iChar ch = 0;[m int n = decodeBytes_MultibyteChar(cursorChar.start,[m [31m- constEnd_String(&constCursorLine_InputWidget_(d)->text),[m [31m- &ch);[m [32m+[m[32m constEnd_String(&constCursorLine_InputWidget_(d)->text),[m [32m+[m[32m &ch);[m cursorChar.end = cursorChar.start + iMax(n, 0);[m if (ch) {[m if (d->inFlags & isSensitive_InputWidgetFlag) {[m [1mdiff --git a/src/ui/labelwidget.c b/src/ui/labelwidget.c[m [1mindex 30eb1d36..c8748efa 100644[m [1m--- a/src/ui/labelwidget.c[m [1m+++ b/src/ui/labelwidget.c[m [36m@@ -611,19 +611,8 @@[m [miBool checkIcon_LabelWidget(iLabelWidget *d) {[m d->icon = 0;[m return iFalse;[m }[m [31m- iStringConstIterator iter;[m [31m- init_StringConstIterator(&iter, &d->label);[m [31m- const iChar icon = iter.value;[m [31m- next_StringConstIterator(&iter);[m [31m- if (iter.value == ' ' && icon >= 0x100) {[m [31m- d->icon = icon;[m [31m- remove_Block(&d->label.chars, 0, iter.next - constBegin_String(&d->label));[m [31m- return iTrue;[m [31m- }[m [31m- else {[m [31m- d->icon = 0;[m [31m- }[m [31m- return iFalse;[m [32m+[m[32m d->icon = removeIconPrefix_String(&d->label);[m [32m+[m[32m return d->icon != 0;[m }[m [m iChar icon_LabelWidget(const iLabelWidget *d) {[m [1mdiff --git a/src/ui/root.c b/src/ui/root.c[m [1mindex 9e290b05..595184cc 100644[m [1m--- a/src/ui/root.c[m [1m+++ b/src/ui/root.c[m [36m@@ -435,6 +435,7 @@[m [mstatic void updateNavBarIdentity_(iWidget *navBar) {[m setOutline_LabelWidget(toolButton, ident == NULL);[m /* Update menu. */[m iLabelWidget *idItem = child_Widget(findChild_Widget(button, "menu"), 0);[m [32m+[m[32m if (!idItem) return;[m const iString *subjectName = ident ? name_GmIdentity(ident) : NULL;[m setTextCStr_LabelWidget([m idItem,[m [1mdiff --git a/src/ui/sidebarwidget.c b/src/ui/sidebarwidget.c[m [1mindex fe33c540..fdfb5300 100644[m [1m--- a/src/ui/sidebarwidget.c[m [1m+++ b/src/ui/sidebarwidget.c[m [36m@@ -1457,40 +1457,25 @@[m [mstatic iBool processEvent_SidebarWidget_(iSidebarWidget *d, const SDL_Event *ev)[m if (d->mode == bookmarks_SidebarMode && d->contextItem) {[m const iBookmark *bm = get_Bookmarks(bookmarks_App(), d->contextItem->id);[m if (bm) {[m [31m- iLabelWidget *menuItem = findMenuItem_Widget(d->menu,[m [31m- "bookmark.tag tag:homepage");[m [31m- if (menuItem) {[m [31m- setTextCStr_LabelWidget(menuItem,[m [31m- hasTag_Bookmark(bm, homepage_BookmarkTag)[m [31m- ? home_Icon " ${bookmark.untag.home}"[m [31m- : home_Icon " ${bookmark.tag.home}");[m [31m- checkIcon_LabelWidget(menuItem);[m [31m- }[m [31m- menuItem = findMenuItem_Widget(d->menu, "bookmark.tag tag:subscribed");[m [31m- if (menuItem) {[m [31m- setTextCStr_LabelWidget(menuItem,[m [31m- hasTag_Bookmark(bm, subscribed_BookmarkTag)[m [32m+[m[32m updateMenuItemLabel_Widget(d->menu, "bookmark.tag tag:homepage",[m [32m+[m[32m hasTag_Bookmark(bm, homepage_BookmarkTag)[m [32m+[m[32m ? home_Icon " ${bookmark.untag.home}"[m [32m+[m[32m : home_Icon " ${bookmark.tag.home}");[m [32m+[m[32m updateMenuItemLabel_Widget(d->menu, "bookmark.tag tag:subscribed",[m [32m+[m[32m hasTag_Bookmark(bm, subscribed_BookmarkTag)[m ? star_Icon " ${bookmark.untag.sub}"[m : star_Icon " ${bookmark.tag.sub}");[m [31m- checkIcon_LabelWidget(menuItem);[m [31m- }[m [31m- menuItem = findMenuItem_Widget(d->menu, "bookmark.tag tag:remotesource");[m [31m- if (menuItem) {[m [31m- setTextCStr_LabelWidget(menuItem,[m [31m- hasTag_Bookmark(bm, remoteSource_BookmarkTag)[m [32m+[m[32m updateMenuItemLabel_Widget(d->menu, "bookmark.tag tag:remotesource",[m [32m+[m[32m hasTag_Bookmark(bm, remoteSource_BookmarkTag)[m ? downArrowBar_Icon " ${bookmark.untag.remote}"[m : downArrowBar_Icon " ${bookmark.tag.remote}");[m [31m- checkIcon_LabelWidget(menuItem);[m [31m- }[m }[m }[m else if (d->mode == feeds_SidebarMode && d->contextItem) {[m [31m- iLabelWidget *menuItem = findMenuItem_Widget(d->menu, "feed.entry.toggleread");[m const iBool isRead = d->contextItem->indent == 0;[m [31m- setTextCStr_LabelWidget(menuItem,[m [31m- isRead ? circle_Icon " ${feeds.entry.markunread}"[m [31m- : circleWhite_Icon " ${feeds.entry.markread}");[m [31m- checkIcon_LabelWidget(menuItem);[m [32m+[m[32m updateMenuItemLabel_Widget(d->menu, "feed.entry.toggleread",[m [32m+[m[32m isRead ? circle_Icon " ${feeds.entry.markunread}"[m [32m+[m[32m : circleWhite_Icon " ${feeds.entry.markread}");[m }[m else if (d->mode == identities_SidebarMode) {[m const iGmIdentity *ident = constHoverIdentity_SidebarWidget_(d);[m [1mdiff --git a/src/ui/util.c b/src/ui/util.c[m [1mindex 38977b96..0baf541d 100644[m [1m--- a/src/ui/util.c[m [1m+++ b/src/ui/util.c[m [36m@@ -44,6 +44,10 @@[m [mSOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */[m # include "../ios.h"[m #endif[m [m [32m+[m[32m#if defined (iPlatformAppleDesktop)[m [32m+[m[32m# include "macos.h"[m [32m+[m[32m#endif[m [32m+[m #include [m #include [m #include [m [36m@@ -749,10 +753,65 @@[m [mvoid makeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n) {[m }[m }[m }[m [31m- }}[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic iArray *deepCopyMenuItems_(iWidget *menu, const iMenuItem *items, size_t n) {[m [32m+[m[32m iArray *array = new_Array(sizeof(iMenuItem));[m [32m+[m[32m iString cmd;[m [32m+[m[32m init_String(&cmd);[m [32m+[m[32m for (size_t i = 0; i < n; i++) {[m [32m+[m[32m const iMenuItem *item = &items[i];[m [32m+[m[32m const char *itemCommand = item->command;[m [32m+[m[32m#if 0[m [32m+[m[32m if (itemCommand) {[m [32m+[m[32m /* Make it appear the command is coming from the right widget. */[m [32m+[m[32m setCStr_String(&cmd, itemCommand);[m [32m+[m[32m if (!hasLabel_Command(itemCommand, "ptr")) {[m [32m+[m[32m size_t firstSpace = indexOf_String(&cmd, ' ');[m [32m+[m[32m iBlock ptr;[m [32m+[m[32m init_Block(&ptr, 0);[m [32m+[m[32m printf_Block(&ptr, " ptr:%p", menu);[m [32m+[m[32m if (firstSpace != iInvalidPos) {[m [32m+[m[32m insertData_Block(&cmd.chars, firstSpace, data_Block(&ptr), size_Block(&ptr));[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m append_Block(&cmd.chars, &ptr);[m [32m+[m[32m }[m [32m+[m[32m deinit_Block(&ptr);[m [32m+[m[32m }[m [32m+[m[32m itemCommand = cstr_String(&cmd);[m [32m+[m[32m }[m [32m+[m[32m#endif[m [32m+[m[32m pushBack_Array(array, &(iMenuItem){[m [32m+[m[32m item->label ? strdup(item->label) : NULL,[m [32m+[m[32m item->key,[m [32m+[m[32m item->kmods,[m [32m+[m[32m itemCommand ? strdup(itemCommand) : NULL /* NOTE: Only works with string commands. */[m [32m+[m[32m });[m [32m+[m[32m }[m [32m+[m[32m deinit_String(&cmd);[m [32m+[m[32m return array;[m [32m+[m[32m}[m [32m+[m [32m+[m[32mstatic void deleteMenuItems_(iArray *items) {[m [32m+[m[32m iForEach(Array, i, items) {[m [32m+[m[32m iMenuItem *item = i.value;[m [32m+[m[32m free((void *) item->label);[m [32m+[m[32m free((void *) item->command);[m [32m+[m[32m }[m [32m+[m[32m delete_Array(items);[m [32m+[m[32m}[m [m iWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {[m iWidget *menu = new_Widget();[m [32m+[m[32m#if defined (iHaveNativeMenus)[m [32m+[m[32m setFlags_Widget(menu, hidden_WidgetFlag | nativeMenu_WidgetFlag, iTrue);[m [32m+[m[32m setUserData_Object(menu, deepCopyMenuItems_(menu, items, n));[m [32m+[m[32m addChild_Widget(parent, menu);[m [32m+[m[32m iRelease(menu); /* owned by parent now */[m [32m+[m[32m#else[m [32m+[m[32m /* Non-native custom popup menu. This may still be displayed inside a separate window. */[m setDrawBufferEnabled_Widget(menu, iTrue);[m setBackgroundColor_Widget(menu, uiBackgroundMenu_ColorId);[m if (deviceType_App() != desktop_AppDeviceType) {[m [36m@@ -777,6 +836,7 @@[m [miWidget *makeMenu_Widget(iWidget *parent, const iMenuItem *items, size_t n) {[m iWidget *cancel = addAction_Widget(menu, SDLK_ESCAPE, 0, "cancel");[m setId_Widget(cancel, "menu.cancel");[m setFlags_Widget(cancel, disabled_WidgetFlag, iTrue);[m [32m+[m[32m#endif[m return menu;[m }[m [m [36m@@ -812,11 +872,52 @@[m [mstatic void updateMenuItemFonts_Widget_(iWidget *d) {[m }[m }[m [m [32m+[m[32mvoid updateMenuItemLabel_Widget(iWidget *menu, const char *command, const char *newLabel) {[m [32m+[m[32m if (~flags_Widget(menu) & nativeMenu_WidgetFlag) {[m [32m+[m[32m iLabelWidget *menuItem = findMenuItem_Widget(menu, command);[m [32m+[m[32m if (menuItem) {[m [32m+[m[32m setTextCStr_LabelWidget(menuItem, newLabel);[m [32m+[m[32m checkIcon_LabelWidget(menuItem);[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m else {[m [32m+[m[32m iArray *items = userData_Object(menu);[m [32m+[m[32m iAssert(items);[m [32m+[m[32m iForEach(Array, i, items) {[m [32m+[m[32m iMenuItem *item = i.value;[m [32m+[m[32m if (item->command && !iCmpStr(item->command, command)) {[m [32m+[m[32m free((void *) item->label);[m [32m+[m[32m item->label = strdup(newLabel);[m [32m+[m[32m break;[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m }[m [32m+[m[32m}[m [32m+[m iLocalDef iBool isUsingMenuPopupWindows_(void) {[m return deviceType_App() == desktop_AppDeviceType;[m }[m [m [32m+[m[32mvoid releaseNativeMenu_Widget(iWidget *d) {[m [32m+[m[32m#if defined (iHaveNativeMenus)[m [32m+[m[32m iArray *items = userData_Object(d);[m [32m+[m[32m iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);[m [32m+[m[32m iAssert(items);[m [32m+[m[32m deleteMenuItems_(items);[m [32m+[m[32m setUserData_Object(d, NULL);[m [32m+[m[32m#else[m [32m+[m[32m iUnused(d);[m [32m+[m[32m#endif[m [32m+[m[32m}[m [32m+[m void openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {[m [32m+[m[32m#if defined (iHaveNativeMenus)[m [32m+[m[32m const iArray *items = userData_Object(d);[m [32m+[m[32m iAssert(flags_Widget(d) & nativeMenu_WidgetFlag);[m [32m+[m[32m iAssert(items);[m [32m+[m[32m showPopupMenu_MacOS(d, mouseCoord_Window(get_Window(), 0),[m [32m+[m[32m constData_Array(items), size_Array(items));[m [32m+[m[32m#else[m const iRect rootRect = rect_Root(d->root);[m const iInt2 rootSize = rootRect.size;[m const iBool isPortraitPhone = (deviceType_App() == phone_AppDeviceType && isPortrait_App());[m [36m@@ -904,9 +1005,13 @@[m [mvoid openMenuFlags_Widget(iWidget *d, iInt2 windowCoord, iBool postCommands) {[m postCommand_Widget(d, "menu.opened");[m }[m setupMenuTransition_Mobile(d, iTrue);[m [32m+[m[32m#endif[m }[m [m void closeMenu_Widget(iWidget *d) {[m [32m+[m[32m if (flags_Widget(d) & nativeMenu_WidgetFlag) {[m [32m+[m[32m return; /* Handled natively. */[m [32m+[m[32m }[m if (d == NULL || flags_Widget(d) & hidden_WidgetFlag) {[m return; /* Already closed. */[m }[m [36m@@ -1780,6 +1885,21 @@[m [msize_t findWidestLabel_MenuItem(const iMenuItem *items, size_t num) {[m return widestPos;[m }[m [m [32m+[m[32miChar removeIconPrefix_String(iString *d) {[m [32m+[m[32m if (isEmpty_String(d)) {[m [32m+[m[32m return 0;[m [32m+[m[32m }[m [32m+[m[32m iStringConstIterator iter;[m [32m+[m[32m init_StringConstIterator(&iter, d);[m [32m+[m[32m iChar icon = iter.value;[m [32m+[m[32m next_StringConstIterator(&iter);[m [32m+[m[32m if (iter.value == ' ' && icon >= 0x100) {[m [32m+[m[32m remove_Block(&d->chars, 0, iter.next - constBegin_String(d));[m [32m+[m[32m return icon;[m [32m+[m[32m }[m [32m+[m[32m return 0;[m [32m+[m[32m}[m [32m+[m iWidget *makeDialog_Widget(const char *id,[m const iMenuItem *itemsNullTerminated,[m const iMenuItem *actions, size_t numActions) {[m [1mdiff --git a/src/ui/util.h b/src/ui/util.h[m [1mindex 3dd4e153..d929143f 100644[m [1m--- a/src/ui/util.h[m [1m+++ b/src/ui/util.h[m [36m@@ -226,16 +226,20 @@[m [mstruct Impl_MenuItem {[m };[m };[m [m [31m-iWidget * makeMenu_Widget (iWidget *parent, const iMenuItem *items, size_t n); /* returns no ref */[m [31m-void makeMenuItems_Widget(iWidget *menu, const iMenuItem *items, size_t n);[m [31m-void openMenu_Widget (iWidget *, iInt2 windowCoord);[m [31m-void openMenuFlags_Widget(iWidget *, iInt2 windowCoord, iBool postCommands);[m [31m-void closeMenu_Widget (iWidget *);[m [32m+[m[32miWidget * makeMenu_Widget (iWidget *parent, const iMenuItem *items, size_t n); /* returns no ref */[m [32m+[m[32mvoid makeMenuItems_Widget (iWidget *menu, const iMenuItem *items, size_t n);[m [32m+[m[32mvoid openMenu_Widget (iWidget *, iInt2 windowCoord);[m [32m+[m[32mvoid openMenuFlags_Widget (iWidget *, iInt2 windowCoord, iBool postCommands);[m [32m+[m[32mvoid closeMenu_Widget (iWidget *);[m [32m+[m[32mvoid releaseNativeMenu_Widget(iWidget *);[m [m size_t findWidestLabel_MenuItem (const iMenuItem *items, size_t num);[m [m [32m+[m[32miChar removeIconPrefix_String (iString *);[m [32m+[m iLabelWidget * findMenuItem_Widget (iWidget *menu, const char *command);[m void setMenuItemDisabled_Widget (iWidget *menu, const char *command, iBool disable);[m [32m+[m[32mvoid updateMenuItemLabel_Widget (iWidget *menu, const char *command, const char *newLabel);[m [m int checkContextMenu_Widget (iWidget *, const SDL_Event *ev); /* see macro below */[m [m [1mdiff --git a/src/ui/widget.c b/src/ui/widget.c[m [1mindex 7b33a752..6b9ee11d 100644[m [1m--- a/src/ui/widget.c[m [1m+++ b/src/ui/widget.c[m [36m@@ -163,6 +163,9 @@[m [mvoid deinit_Widget(iWidget *d) {[m if (win->hover == d) {[m win->hover = NULL;[m }[m [32m+[m[32m if (d->flags & nativeMenu_WidgetFlag) {[m [32m+[m[32m releaseNativeMenu_Widget(d);[m [32m+[m[32m }[m widgetDestroyed_Touch(d);[m }[m [m [1mdiff --git a/src/ui/widget.h b/src/ui/widget.h[m [1mindex 0eab69c1..9243c00a 100644[m [1m--- a/src/ui/widget.h[m [1m+++ b/src/ui/widget.h[m [36m@@ -121,6 +121,7 @@[m [menum iWidgetFlag {[m #define destroyPending_WidgetFlag iBit64(61)[m #define leftEdgeDraggable_WidgetFlag iBit64(62)[m #define refChildrenOffset_WidgetFlag iBit64(63) /* visual offset determined by the offset of referenced children */[m [32m+[m[32m#define nativeMenu_WidgetFlag iBit64(64)[m [m enum iWidgetAddPos {[m back_WidgetAddPos,[m
text/gemini; charset=utf-8
This content has been proxied by September (ba2dc).