@@ -92,6 +92,7 @@ @interface WineApplicationController ()
92
92
@property (retain , nonatomic ) NSTimer * cursorTimer;
93
93
@property (retain , nonatomic ) NSCursor * cursor;
94
94
@property (retain , nonatomic ) NSImage * applicationIcon;
95
+ @property (copy , nonatomic ) NSString * applicationName;
95
96
@property (readonly , nonatomic ) BOOL inputSourceIsInputMethod;
96
97
@property (retain , nonatomic ) WineWindow* mouseCaptureWindow;
97
98
@@ -108,6 +109,7 @@ @implementation WineApplicationController
108
109
@synthesize keyboardType, lastFlagsChanged;
109
110
@synthesize displaysTemporarilyUncapturedForDialog, temporarilyIgnoreResignEventsForDialog;
110
111
@synthesize applicationIcon;
112
+ @synthesize applicationName;
111
113
@synthesize cursorFrames, cursorTimer, cursor;
112
114
@synthesize mouseCaptureWindow;
113
115
@synthesize lastSetCursorPositionTime;
@@ -201,6 +203,7 @@ - (void) dealloc
201
203
[cursor release ];
202
204
[screenFrameCGRects release ];
203
205
[applicationIcon release ];
206
+ [applicationName release ];
204
207
[clipCursorHandler release ];
205
208
[cursorTimer release ];
206
209
[cursorFrames release ];
@@ -384,6 +387,13 @@ - (void) transformProcessToForeground:(BOOL)activateIfTransformed
384
387
[self changeEditMenuKeyEquivalentsForWindow: [NSApp keyWindow ]];
385
388
386
389
[NSApp setApplicationIconImage: self .applicationIcon];
390
+
391
+ // Set application name
392
+ NSString * appName = [NSString stringWithFormat: @" WhiskyWine (%@ )" , self .applicationName];
393
+ bool success = [self setProcessName: appName];
394
+ if (!success)
395
+ ERR (@" Failed to set process name to %@ " , appName);
396
+ [appName release ];
387
397
}
388
398
}
389
399
@@ -833,6 +843,109 @@ - (void) sendDisplaysChanged:(BOOL)activating
833
843
macdrv_release_event (event);
834
844
}
835
845
846
+ - (BOOL ) setProcessName:(NSString *)name
847
+ {
848
+ // Convert the name to a CFString
849
+ CFStringRef cfName = (CFStringRef )name;
850
+
851
+ // Must be called on the main thread
852
+ if (![NSThread isMainThread ]) {
853
+ ERR (@" setProcessName: must be called on the main thread" );
854
+ return false ;
855
+ }
856
+
857
+ // New name can't be NULL or empty
858
+ if (!cfName || CFStringGetLength (cfName) == 0 ) {
859
+ ERR (@" setProcessName: Invalid process name" );
860
+ return false ;
861
+ }
862
+
863
+ // Private types used in calls to launch services
864
+ typedef CFTypeRef PrivateLaunchRef;
865
+ typedef PrivateLaunchRef (*LSGetCurrentApplicationASNType)(void );
866
+ typedef OSStatus (*LSSetApplicationInformationItemType)(
867
+ int ,
868
+ PrivateLaunchRef,
869
+ CFStringRef ,
870
+ CFStringRef ,
871
+ CFDictionaryRef
872
+ );
873
+
874
+ // Static so we can reuse the same function pointers
875
+ static bool initialized = false ;
876
+ static LSGetCurrentApplicationASNType getCurrentAppASNFunc = NULL ;
877
+ static LSSetApplicationInformationItemType setAppInfoFunc = NULL ;
878
+ static CFStringRef launchServicesDisplayNameKey = NULL ;
879
+
880
+ // Initialize the function pointers
881
+ if (!initialized) {
882
+ initialized = true ;
883
+
884
+ // Get the bundle for the LaunchServices framework
885
+ CFBundleRef launchServicesBundle = CFBundleGetBundleWithIdentifier (CFSTR (" com.apple.LaunchServices" ));
886
+ if (!launchServicesBundle) {
887
+ ERR (@" setProcessName: Failed to get LaunchServices bundle" );
888
+ return false ;
889
+ }
890
+
891
+ // Get the function pointers
892
+ getCurrentAppASNFunc = (LSGetCurrentApplicationASNType)(
893
+ CFBundleGetFunctionPointerForName (launchServicesBundle, CFSTR (" _LSGetCurrentApplicationASN" ))
894
+ );
895
+ if (!getCurrentAppASNFunc) {
896
+ ERR (@" setProcessName: Failed to get _LSGetCurrentApplicationASN in LaunchServices" );
897
+ return false ;
898
+ }
899
+ setAppInfoFunc = (LSSetApplicationInformationItemType)(
900
+ CFBundleGetFunctionPointerForName (launchServicesBundle, CFSTR (" _LSSetApplicationInformationItem" ))
901
+ );
902
+ if (!setAppInfoFunc) {
903
+ ERR (@" setProcessName: Failed to get _LSSetApplicationInformationItem in LaunchServices" );
904
+ return false ;
905
+ }
906
+
907
+ // Get the display name key
908
+ const CFStringRef * displayNameKey = (const CFStringRef *)(
909
+ CFBundleGetDataPointerForName (launchServicesBundle, CFSTR (" _kLSDisplayNameKey" ))
910
+ );
911
+ launchServicesDisplayNameKey = displayNameKey ? *displayNameKey : NULL ;
912
+ if (!launchServicesDisplayNameKey) {
913
+ ERR (@" setProcessName: Failed to get _kLSDisplayNameKey in LaunchServices" );
914
+ return false ;
915
+ }
916
+
917
+ // Force symbols to be loaded in the LaunchServices framework
918
+ ProcessSerialNumber psn = {0 , kCurrentProcess };
919
+ GetCurrentProcess (&psn);
920
+ }
921
+
922
+ // If any of the function pointers are NULL, we can't continue
923
+ if (!getCurrentAppASNFunc || !setAppInfoFunc || !launchServicesDisplayNameKey) {
924
+ ERR (@" setProcessName: Failed to get all required LaunchServices functions" );
925
+ return false ;
926
+ }
927
+
928
+ // Get the current application's ASN
929
+ PrivateLaunchRef currentAppASN = getCurrentAppASNFunc ();
930
+
931
+ // Set the display name
932
+ OSErr err = setAppInfoFunc (
933
+ -2 , // WebKit uses -2
934
+ currentAppASN,
935
+ launchServicesDisplayNameKey,
936
+ cfName,
937
+ NULL // Output parameter
938
+ );
939
+
940
+ // Log any errors
941
+ if (err != noErr ) {
942
+ ERR (@" WHISKYEXTRA: Failed to set process name: %d " , err);
943
+ return false ;
944
+ }
945
+
946
+ return true ;
947
+ }
948
+
836
949
// We can compare two modes directly using CFEqual, but that may require that
837
950
// they are identical to a level that we don't need. In particular, when the
838
951
// OS switches between the integrated and discrete GPUs, the set of display
@@ -1176,6 +1289,12 @@ - (void) setApplicationIconFromCGImageArray:(NSArray*)images
1176
1289
self.applicationIcon = nsimage;
1177
1290
}
1178
1291
1292
+ - (void ) setApplicationName:(NSString *)name
1293
+ {
1294
+ [applicationName release ];
1295
+ applicationName = [name copy ];
1296
+ }
1297
+
1179
1298
- (void ) handleCommandTab
1180
1299
{
1181
1300
if ([NSApp isActive ])
@@ -2634,6 +2753,21 @@ void macdrv_set_application_icon(CFArrayRef images, CFURLRef urlRef)
2634
2753
});
2635
2754
}
2636
2755
2756
+ /* **********************************************************************
2757
+ * macdrv_set_application_name
2758
+ *
2759
+ * Set the application name.
2760
+ */
2761
+ void macdrv_set_application_name (CFStringRef name)
2762
+ {
2763
+ NSString * nsName = (NSString *)name;
2764
+
2765
+ OnMainThreadAsync (^{
2766
+ WineApplicationController* controller = [WineApplicationController sharedController ];
2767
+ [controller setApplicationName: nsName];
2768
+ });
2769
+ }
2770
+
2637
2771
/* **********************************************************************
2638
2772
* macdrv_quit_reply
2639
2773
*/
0 commit comments