From 28adad607703690ae442a0de4ab19e2e4c561931 Mon Sep 17 00:00:00 2001 From: armm77 Date: Sun, 21 Jun 2026 21:49:42 -0500 Subject: [PATCH] Fix non-functional File Creation Mask in Preferences Expert module The File Creation Mask grid rendered empty and did nothing because the WMPermissions custom view composites its PermYes/PermNo/PermNoChange TIFF glyphs from the module bundle, but those resources existed only in the Workspace Inspectors and were never bundled into Expert.preferences, so pathForResource: returned nil. The controller also never finished wiring the view: displaysExecute was left NO (hiding the Execute row), the matrix was never seeded, and changes were neither captured nor persisted. Make Preferences File Creation Mask take effect immediately - Expert.m: post the distributed notification after persisting the mask. - Controller.m: apply the saved umask on startup, observe the notification, and re-apply on change. - Bundle PermYes/PermNo/PermNoChange.tiff with the Expert module. - Locate the WMPermissions view in awakeFromNib, enable the Execute row, seed it from the saved umask (falling back to the process umask), and set target/action. - Persist the chosen mask to OSEDefaults (NXFileCreationMask) as a POSIX umask on change. --- .../Preferences/Modules/Expert/Expert.h | 2 + .../Preferences/Modules/Expert/Expert.m | 84 ++++++++++++++++++ .../Preferences/Modules/Expert/GNUmakefile | 5 +- .../Modules/Expert/Resources/PermNo.tiff | Bin 0 -> 650 bytes .../Expert/Resources/PermNoChange.tiff | Bin 0 -> 600 bytes .../Modules/Expert/Resources/PermYes.tiff | Bin 0 -> 636 bytes Applications/Workspace/Controller.m | 30 +++++++ 7 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 Applications/Preferences/Modules/Expert/Resources/PermNo.tiff create mode 100644 Applications/Preferences/Modules/Expert/Resources/PermNoChange.tiff create mode 100644 Applications/Preferences/Modules/Expert/Resources/PermYes.tiff diff --git a/Applications/Preferences/Modules/Expert/Expert.h b/Applications/Preferences/Modules/Expert/Expert.h index c0f10551c..15aad8274 100644 --- a/Applications/Preferences/Modules/Expert/Expert.h +++ b/Applications/Preferences/Modules/Expert/Expert.h @@ -34,6 +34,8 @@ id privateWindowServerBtn; id privateSoundServerBtn; + id permissionsView; + OSEDefaults *defaults; NSImage *image; } diff --git a/Applications/Preferences/Modules/Expert/Expert.m b/Applications/Preferences/Modules/Expert/Expert.m index e9954b66a..6cdd339c5 100644 --- a/Applications/Preferences/Modules/Expert/Expert.m +++ b/Applications/Preferences/Modules/Expert/Expert.m @@ -20,9 +20,27 @@ // #import +#import #import +#import +#import + #import "Expert.h" +#import "WMPermissions.h" + +// Global defaults key holding the file-creation umask (octal), e.g. 022. +// The value is the POSIX umask -- the complement of the permission bits +// granted to newly created files and folders. Workspace (the session +// leader) applies it with umask() at startup and again, live, whenever +// this module posts FileCreationMaskDidChangeNotification, so the setting +// takes effect immediately without re-logging in. +static NSString * const FileCreationMaskKey = @"NXFileCreationMask"; + +// Posted (distributed) when the user edits the mask so Workspace re-applies +// it to the running session. Mirrors the Font module's live-apply pattern. +static NSString * const FileCreationMaskDidChangeNotification = + @"NXFileCreationMaskDidChangeNotification"; @implementation Expert @@ -62,6 +80,57 @@ - (void)awakeFromNib selectItemWithTag:[[OSEFileManager defaultManager] sortFilesBy]]; [showHiddenFilesBtn setState:[[OSEFileManager defaultManager] isShowHiddenFiles]]; + + // The "File Creation Mask" control is a WMPermissions custom view placed + // in the NIB. It is not wired to a Gorm connection, so locate it in the + // loaded view hierarchy and finish its setup here. + permissionsView = [self permissionsViewInView:view]; + if (permissionsView != nil) { + unsigned long grantedMode; + mode_t mask; + + // Show all three permission rows (Read/Write/Execute) to match the + // Owner/Group/Others x Read/Write/Execute layout of the panel. + [permissionsView setDisplaysExecute:YES]; + [permissionsView setEditable:YES]; + [permissionsView setTarget:self]; + [permissionsView setAction:@selector(setFileCreationMask:)]; + + // Seed the matrix from the saved default; fall back to the current + // process umask when the key is absent (objectForKey: nil-check, since + // a "default present" semantics cannot be expressed with boolForKey:). + if ([defaults objectForKey:FileCreationMaskKey] != nil) { + mask = (mode_t)[defaults integerForKey:FileCreationMaskKey]; + } else { + mask = umask(0); // read current umask ... + umask(mask); // ... and restore it immediately + } + // WMPermissions displays *granted* permission bits, i.e. the complement + // of the umask, limited to the rwxrwxrwx (0777) range. + grantedMode = (~mask) & 0777; + [permissionsView setMode:grantedMode]; + } +} + +// Depth-first search for the WMPermissions view loaded from the NIB. +- (id)permissionsViewInView:(NSView *)aView +{ + NSArray *subviews = [aView subviews]; + NSUInteger i, count = [subviews count]; + + for (i = 0; i < count; i++) { + NSView *subview = [subviews objectAtIndex:i]; + id found; + + if ([subview isKindOfClass:[WMPermissions class]]) { + return subview; + } + found = [self permissionsViewInView:subview]; + if (found != nil) { + return found; + } + } + return nil; } - (NSView *)view @@ -102,5 +171,20 @@ - (void)setShowHiddenFiles:(id)sender [[OSEFileManager defaultManager] setShowHiddenFiles:[sender state]]; } +- (void)setFileCreationMask:(id)sender +{ + unsigned long grantedMode = [(WMPermissions *)sender mode] & 0777; + mode_t mask = (mode_t)((~grantedMode) & 0777); + + // Persist as the POSIX umask, then notify Workspace so it re-applies the + // mask to the running session immediately (no re-login required). + [defaults setInteger:(NSInteger)mask forKey:FileCreationMaskKey]; + [defaults synchronize]; + + [[NSDistributedNotificationCenter defaultCenter] + postNotificationName:FileCreationMaskDidChangeNotification + object:@"Preferences"]; +} + @end diff --git a/Applications/Preferences/Modules/Expert/GNUmakefile b/Applications/Preferences/Modules/Expert/GNUmakefile index 829c79f66..96224a7ab 100644 --- a/Applications/Preferences/Modules/Expert/GNUmakefile +++ b/Applications/Preferences/Modules/Expert/GNUmakefile @@ -18,7 +18,10 @@ $(BUNDLE_NAME)_HEADERS= \ $(BUNDLE_NAME)_RESOURCE_FILES = \ Resources/Expert.tiff \ - Resources/bundle.registry + Resources/bundle.registry \ + Resources/PermYes.tiff \ + Resources/PermNo.tiff \ + Resources/PermNoChange.tiff $(BUNDLE_NAME)_LANGUAGES = \ English diff --git a/Applications/Preferences/Modules/Expert/Resources/PermNo.tiff b/Applications/Preferences/Modules/Expert/Resources/PermNo.tiff new file mode 100644 index 0000000000000000000000000000000000000000..a1e10e9086cbd222ae26b3ddf1e596b52182ab4c GIT binary patch literal 650 zcmebEWzb?^VA!#WD6sk!OxdyZS}^9uJy|g3nvXEns?}_8=6VEkPa$0N0|PVA<%|qEK!Op<767uDpll`}n;FUmDrRIuVhb{`fb}vka4?D@ ziHpOw89U|>)efYA+F3j!=u#CX|ToDu_e zq?pO_ceo@4S}X|-Szo{ZeqhEE*?%7xM7;w%PXA%x>N}M%v4KHkwRq17m7tYNxa=4v zolgB6`D6p5;>7c6n`izx*Q(j$dur)VlU@BXb1pBtti@}m>b2^?(n(!gxlCg>MC627 ztH?1i@Dd0aV5l*bz(WS;M|jA9LJS@pC(4T&wtzyj9Gz`(&MiX<)$7vI1r#lQ+t!|2B-4QGcj${?AqfnWn|Sir#br-6Y% zT>wTmXe|h^P!Z#0Z*fWt*pXr;%irOW6lk#|Ojo?eEje(R=Ru`IGSj fBf`&42tPA~1ez@Y?dB=a>8Y@iKC7`Xm4FfgbKz~~081pyW+V!Z4vPKg0KQp{xeJ6w_i zEtZ7w{I7Lg94K1-hk>j2L}LH<28LBp6FrtRaHy0puxg!3HQFJw&fjR}Nw1|pz8oqv zs^9CiIn(7|+W&cHGOlo56`QU({nE;>R!hUyhIbxtVBjSX7Qk>~N`r?5&{y!V0EH1e uEEwb9VFA>^C #import #import +#import #import #import +#import #include #include @@ -674,6 +676,34 @@ - (void)applicationWillFinishLaunching:(NSNotification *)notif selector:@selector(applicationDidChangeScreenParameters:) name:NSApplicationDidChangeScreenParametersNotification object:NSApp]; + + // File creation mask (umask): apply the saved value to this session leader + // now, and re-apply it live whenever the Preferences Expert module changes + // it, so the setting takes effect without re-logging in. + [self applyFileCreationMask]; + [[NSDistributedNotificationCenter defaultCenter] + addObserver:self + selector:@selector(fileCreationMaskDidChange:) + name:@"NXFileCreationMaskDidChangeNotification" + object:@"Preferences"]; +} + +// Read the saved file-creation umask from the global defaults and apply it to +// the Workspace process. Folders/files created by the File Viewer and every +// application Workspace launches afterwards inherit this umask. Already +// running applications keep the umask they inherited at their own launch. +- (void)applyFileCreationMask +{ + OSEDefaults *defs = [OSEDefaults globalUserDefaults]; + + if ([defs objectForKey:@"NXFileCreationMask"] != nil) { + umask((mode_t)[defs integerForKey:@"NXFileCreationMask"]); + } +} + +- (void)fileCreationMaskDidChange:(NSNotification *)aNotif +{ + [self applyFileCreationMask]; } - (void)applicationDidFinishLaunching:(NSNotification *)notif