Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 1 addition & 4 deletions Headers/AppKit/NSDockTile.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,8 +59,7 @@
extern "C" {
#endif

@class NSView, NSString;
@class NSImageRep;
@class NSView, NSString, NSImage;

APPKIT_EXPORT_CLASS
@interface NSDockTile : NSObject
Expand All @@ -71,7 +70,6 @@ APPKIT_EXPORT_CLASS
BOOL _showsApplicationBadge;
NSString *_badgeLabel;
NSImage *_appIconImage;
NSImage *_dockTileImage;
}

/**
Expand Down Expand Up @@ -143,4 +141,3 @@ APPKIT_EXPORT_CLASS
#endif /* GS_API_MACOSX */

#endif /* _NSDockTile_h_GNUSTEP_GUI_INCLUDE */

8 changes: 8 additions & 0 deletions Source/GSIconManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@

#import <Foundation/NSGeometry.h>

@class NSImage;
@class NSString;
#import "AppKit/NSWindow.h"

NSSize
Expand All @@ -34,3 +36,9 @@ GSRemoveIcon(NSWindow *window);

NSRect
GSGetIconFrame(NSWindow *window);

void
GSUpdateIconManager(NSImage *image, NSString *badgeLabel);

void
GSRequestUserAttention(NSUInteger requestType);
273 changes: 253 additions & 20 deletions Source/GSIconManager.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,43 +23,135 @@
*/

#import <Foundation/NSConnection.h>
#import <Foundation/NSData.h>
#import <Foundation/NSDistantObject.h>
#import <Foundation/NSException.h>
#import <Foundation/NSNotification.h>
#import <Foundation/NSObject.h>
#import <Foundation/NSSet.h>
#import <Foundation/NSUserDefaults.h>
#import <Foundation/NSValue.h>
#import <Foundation/NSProcessInfo.h>

#import <GNUstepGUI/GSDisplayServer.h>
#import "AppKit/NSGraphics.h"
#import "AppKit/NSImage.h"
#import "GSIconManager.h"

@protocol GSIconManager
@protocol GSIconManager <NSObject>
- (NSRect) setWindow: (unsigned int)aWindowNumber appProcessId: (int)aProcessId;
- (void) removeWindow: (unsigned int)aWindowNumber;
- (NSSize) getSizeWindow;
- (id) retain;
- (void) release;
- (void) setApplicationIconData: (NSData *)data
badgeText: (NSString *)badgeText
appProcessId: (int)aProcessId;
- (void) requestUserAttention: (NSInteger)requestType
appProcessId: (int)aProcessId;
@end

static BOOL verify = NO;
static id <GSIconManager>gsim = nil;
static NSConnection *gsimConnection = nil;
static int appId = 0;
static int iconCount = 0;
static NSMutableSet *registeredIcons = nil;
static unsigned int iconManagerUpdateCount = 0;
static unsigned int lastIconManagerAttemptUpdate = 0;
static NSData *lastApplicationIconData = nil;
static NSString *lastApplicationIconBadgeText = nil;

static void GSReleaseIconManager(void);
static void GSLostIconManager(void);
static BOOL GSSendApplicationIconData(NSData *data, NSString *badgeText);

@interface GSIconManagerMonitor : NSObject
+ (id) _lostIconManager: (NSNotification *)notification;
@end

@implementation GSIconManagerMonitor
+ (id) _lostIconManager: (NSNotification *)notification
{
if ([notification object] == gsimConnection)
{
GSLostIconManager();
}
return self;
}
@end

static void
GSGetIconManager(void)
{
if ([[NSUserDefaults standardUserDefaults] boolForKey: @"GSUseIconManager"])
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

lastIconManagerAttemptUpdate = iconManagerUpdateCount;

if ([defaults objectForKey: @"GSUseIconManager"] == nil ||
[defaults boolForKey: @"GSUseIconManager"])
{
id <GSIconManager>proxy = nil;
BOOL retainedProxy = NO;

appId = [[NSProcessInfo processInfo] processIdentifier];

gsim = (id <GSIconManager>)[NSConnection rootProxyForConnectionWithRegisteredName: @"GSIconManager"
host: @""];

if (gsim == nil)
NS_DURING
{
NSLog (@"Error: could not connect to server GSIconManager");
proxy = (id <GSIconManager>)
[NSConnection rootProxyForConnectionWithRegisteredName: @"GSIconManager"
host: @""];

if (proxy != nil && RETAIN(proxy) != nil)
{
retainedProxy = YES;
gsimConnection = RETAIN([(NSDistantObject *)proxy connectionForProxy]);
gsim = proxy;
[[NSNotificationCenter defaultCenter]
addObserver: [GSIconManagerMonitor class]
selector: @selector(_lostIconManager:)
name: NSConnectionDidDieNotification
object: gsimConnection];
if (lastApplicationIconData != nil
|| lastApplicationIconBadgeText != nil)
{
GSSendApplicationIconData(lastApplicationIconData,
lastApplicationIconBadgeText);
}
}
}
NS_HANDLER
{
if (retainedProxy == YES)
{
RELEASE(proxy);
}
DESTROY(gsimConnection);
gsim = nil;
}
NS_ENDHANDLER
}
}

[gsim retain];
static void
GSReleaseIconManager(void)
{
if (gsimConnection != nil)
{
[[NSNotificationCenter defaultCenter]
removeObserver: [GSIconManagerMonitor class]
name: NSConnectionDidDieNotification
object: gsimConnection];
DESTROY(gsimConnection);
}
DESTROY(gsim);
verify = NO;
}

static void
GSLostIconManager(void)
{
GSReleaseIconManager();
[registeredIcons removeAllObjects];
verify = YES;
lastIconManagerAttemptUpdate = iconManagerUpdateCount;
}

static inline void
Expand All @@ -81,7 +173,16 @@ - (void) release;

if (gsim != nil)
{
iconSize = [gsim getSizeWindow];
NS_DURING
{
iconSize = [gsim getSizeWindow];
}
NS_HANDLER
{
GSLostIconManager();
iconSize = [GSCurrentServer() iconSize];
}
NS_ENDHANDLER
}
else
{
Expand All @@ -99,18 +200,129 @@ - (void) release;
if (gsim != nil)
{
unsigned int winNum = 0;
BOOL removed = NO;
NSNumber *winNumObject;

NSConvertWindowNumberToGlobal([window windowNumber], &winNum);
[gsim removeWindow: winNum];
winNumObject = [NSNumber numberWithUnsignedInt: winNum];

if ([registeredIcons containsObject: winNumObject] == NO)
{
return;
}

NS_DURING
{
[gsim removeWindow: winNum];
removed = YES;
}
NS_HANDLER
{
GSLostIconManager();
}
NS_ENDHANDLER

if (removed == NO)
{
return;
}

[registeredIcons removeObject: winNumObject];

if ([registeredIcons count] == 0)
{
GSReleaseIconManager();
}
}
}

void
GSUpdateIconManager(NSImage *image, NSString *badgeLabel)
{
NSData *iconData = nil;

iconManagerUpdateCount++;

iconCount--;
if (image != nil)
{
iconData = [image TIFFRepresentation];
}
ASSIGN(lastApplicationIconData, iconData);
ASSIGNCOPY(lastApplicationIconBadgeText, badgeLabel);

if (iconCount == 0)
if (gsim == nil && verify)
{
if (iconManagerUpdateCount - lastIconManagerAttemptUpdate < 5)
{
DESTROY(gsim);
verify = NO;
return;
}

verify = NO;
}

checkVerify();

if (gsim == nil)
{
return;
}

GSSendApplicationIconData(lastApplicationIconData,
lastApplicationIconBadgeText);
}

static BOOL
GSSendApplicationIconData(NSData *data, NSString *badgeText)
{
BOOL sent = NO;

if (gsim == nil)
{
return NO;
}

NS_DURING
{
if ([gsim respondsToSelector: @selector(setApplicationIconData:badgeText:appProcessId:)])
{
[gsim setApplicationIconData: data
badgeText: badgeText
appProcessId: appId];
sent = YES;
}
}
NS_HANDLER
{
GSLostIconManager();
}
NS_ENDHANDLER

return sent;
}

void
GSRequestUserAttention(NSUInteger requestType)
{
checkVerify();

if (gsim == nil)
{
return;
}

NS_DURING
{
if ([gsim respondsToSelector: @selector(requestUserAttention:appProcessId:)])
{
[gsim requestUserAttention: requestType
appProcessId: appId];
}
}
NS_HANDLER
{
GSLostIconManager();
}
NS_ENDHANDLER
}

NSRect
Expand All @@ -123,12 +335,33 @@ - (void) release;
if (gsim != nil)
{
unsigned int winNum = 0;
BOOL added = NO;
NSNumber *winNumObject;

NSConvertWindowNumberToGlobal([window windowNumber], &winNum);
iconRect = [gsim setWindow: winNum
appProcessId: appId];
NS_DURING
{
iconRect = [gsim setWindow: winNum
appProcessId: appId];
added = YES;
}
NS_HANDLER
{
GSLostIconManager();
iconRect = [window frame];
iconRect.size = [GSCurrentServer() iconSize];
}
NS_ENDHANDLER

iconCount++;
if (added == YES)
{
winNumObject = [NSNumber numberWithUnsignedInt: winNum];
if (registeredIcons == nil)
{
registeredIcons = [[NSMutableSet alloc] initWithCapacity: 1];
}
[registeredIcons addObject: winNumObject];
}
}
else
{
Expand Down
Loading