Skip to content

Commit 74d1380

Browse files
committed
Set application name in macOS driver
1 parent 6821529 commit 74d1380

File tree

4 files changed

+165
-0
lines changed

4 files changed

+165
-0
lines changed

dlls/winemac.drv/cocoa_app.h

+2
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,8 @@ enum {
128128

129129
NSImage* applicationIcon;
130130

131+
NSString* applicationName;
132+
131133
BOOL beenActive;
132134

133135
NSMutableSet* windowsBeingDragged;

dlls/winemac.drv/cocoa_app.m

+134
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,7 @@ @interface WineApplicationController ()
9292
@property (retain, nonatomic) NSTimer* cursorTimer;
9393
@property (retain, nonatomic) NSCursor* cursor;
9494
@property (retain, nonatomic) NSImage* applicationIcon;
95+
@property (copy, nonatomic) NSString* applicationName;
9596
@property (readonly, nonatomic) BOOL inputSourceIsInputMethod;
9697
@property (retain, nonatomic) WineWindow* mouseCaptureWindow;
9798

@@ -108,6 +109,7 @@ @implementation WineApplicationController
108109
@synthesize keyboardType, lastFlagsChanged;
109110
@synthesize displaysTemporarilyUncapturedForDialog, temporarilyIgnoreResignEventsForDialog;
110111
@synthesize applicationIcon;
112+
@synthesize applicationName;
111113
@synthesize cursorFrames, cursorTimer, cursor;
112114
@synthesize mouseCaptureWindow;
113115
@synthesize lastSetCursorPositionTime;
@@ -201,6 +203,7 @@ - (void) dealloc
201203
[cursor release];
202204
[screenFrameCGRects release];
203205
[applicationIcon release];
206+
[applicationName release];
204207
[clipCursorHandler release];
205208
[cursorTimer release];
206209
[cursorFrames release];
@@ -384,6 +387,13 @@ - (void) transformProcessToForeground:(BOOL)activateIfTransformed
384387
[self changeEditMenuKeyEquivalentsForWindow:[NSApp keyWindow]];
385388

386389
[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];
387397
}
388398
}
389399

@@ -833,6 +843,109 @@ - (void) sendDisplaysChanged:(BOOL)activating
833843
macdrv_release_event(event);
834844
}
835845

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+
836949
// We can compare two modes directly using CFEqual, but that may require that
837950
// they are identical to a level that we don't need. In particular, when the
838951
// OS switches between the integrated and discrete GPUs, the set of display
@@ -1176,6 +1289,12 @@ - (void) setApplicationIconFromCGImageArray:(NSArray*)images
11761289
self.applicationIcon = nsimage;
11771290
}
11781291

1292+
- (void) setApplicationName:(NSString*)name
1293+
{
1294+
[applicationName release];
1295+
applicationName = [name copy];
1296+
}
1297+
11791298
- (void) handleCommandTab
11801299
{
11811300
if ([NSApp isActive])
@@ -2634,6 +2753,21 @@ void macdrv_set_application_icon(CFArrayRef images, CFURLRef urlRef)
26342753
});
26352754
}
26362755

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+
26372771
/***********************************************************************
26382772
* macdrv_quit_reply
26392773
*/

dlls/winemac.drv/macdrv_cocoa.h

+1
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ extern int macdrv_start_cocoa_app(unsigned long long tickcount) DECLSPEC_HIDDEN;
266266
extern void macdrv_window_rejected_focus(const struct macdrv_event *event) DECLSPEC_HIDDEN;
267267
extern void macdrv_beep(void) DECLSPEC_HIDDEN;
268268
extern void macdrv_set_application_icon(CFArrayRef images, CFURLRef url /* CrossOver Hack 13440 */) DECLSPEC_HIDDEN;
269+
extern void macdrv_set_application_name(CFStringRef name) DECLSPEC_HIDDEN;
269270
extern void macdrv_quit_reply(int reply) DECLSPEC_HIDDEN;
270271
extern int macdrv_using_input_method(void) DECLSPEC_HIDDEN;
271272
extern void macdrv_set_mouse_capture_window(macdrv_window window) DECLSPEC_HIDDEN;

dlls/winemac.drv/window.c

+28
Original file line numberDiff line numberDiff line change
@@ -1355,6 +1355,33 @@ static void set_app_icon(void)
13551355
}
13561356
}
13571357

1358+
/***********************************************************************
1359+
* set_app_name
1360+
*/
1361+
static void set_app_name(void)
1362+
{
1363+
WCHAR app_name[MAX_PATH];
1364+
DWORD len = GetModuleFileNameW(0, app_name, ARRAY_SIZE(app_name));
1365+
1366+
// Get offset to the last backslash
1367+
DWORD last_char_pos = 0;
1368+
for (DWORD i = 0; i < len; i++)
1369+
{
1370+
if (app_name[i] == '\\')
1371+
last_char_pos = i;
1372+
}
1373+
1374+
if (len && len < ARRAY_SIZE(app_name))
1375+
{
1376+
CFStringRef name = CFStringCreateWithCharacters(NULL, app_name + last_char_pos + 1, len - last_char_pos - 1);
1377+
if (name)
1378+
{
1379+
macdrv_set_application_name(name);
1380+
CFRelease(name);
1381+
}
1382+
}
1383+
}
1384+
13581385

13591386
/**********************************************************************
13601387
* set_capture_window_for_move
@@ -1661,6 +1688,7 @@ BOOL macdrv_CreateDesktopWindow(HWND hwnd)
16611688
}
16621689

16631690
set_app_icon();
1691+
set_app_name();
16641692
return TRUE;
16651693
}
16661694

0 commit comments

Comments
 (0)