On Sat, Mar 8, 2008 at 2:14 AM, Dave MacLachlan <dmacl
...@gmail.com> wrote:
> Allows us to detect when a screensaver is up. Is required for a future
> check in that I am going to add to greatly expand upon the unittesting
> code that is in the toolbox.
> Index: GTM.xcodeproj/project.pbxproj
> ===================================================================
> --- GTM.xcodeproj/project.pbxproj (revision 12)
> +++ GTM.xcodeproj/project.pbxproj (working copy)
> @@ -22,6 +22,12 @@
> /* End PBXAggregateTarget section */
> /* Begin PBXBuildFile section */
> + 8B2A9B200D8270DA00599386 /* GTMNSWorkspace+ScreenSaver.m
> in Sources
> */ = {isa = PBXBuildFile; fileRef = 8B2A9B1D0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.m */; };
> + 8B2A9B220D8270DA00599386 /* GTMNSWorkspace+ScreenSaver.h
> in Headers
> */ = {isa = PBXBuildFile; fileRef = 8B2A9B1F0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.h */; };
> + 8B2A9B230D8270DA00599386 /* GTMNSWorkspace+ScreenSaver.m
> in Sources
> */ = {isa = PBXBuildFile; fileRef = 8B2A9B1D0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.m */; };
> + 8B2A9B240D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaverTest.m in
> Sources */ = {isa = PBXBuildFile; fileRef = 8B2A9B1E0D8270DA00599386 /
> * GTMNSWorkspace+ScreenSaverTest.m */; };
> + 8B2A9BEC0D82714A00599386 /* ScreenSaver.framework in
> Frameworks */
> = {isa = PBXBuildFile; fileRef = 8B2A9BEB0D82714A00599386 /*
> ScreenSaver.framework */; };
> + 8B2A9BED0D82714A00599386 /* ScreenSaver.framework in
> Frameworks */
> = {isa = PBXBuildFile; fileRef = 8B2A9BEB0D82714A00599386 /*
> ScreenSaver.framework */; };
> F413908F0D75F63C00F72B31 /* GTMNSFileManager+Path.h in
> Headers */
> = {isa = PBXBuildFile; fileRef = F413908C0D75F63C00F72B31 /*
> GTMNSFileManager+Path.h */; };
> F41390900D75F63C00F72B31 /* GTMNSFileManager+Path.m in
> Sources */
> = {isa = PBXBuildFile; fileRef = F413908D0D75F63C00F72B31 /*
> GTMNSFileManager+Path.m */; };
> F41390920D75F64D00F72B31 /* GTMNSFileManager+PathTest.m in
> Sources
> */ = {isa = PBXBuildFile; fileRef = F413908E0D75F63C00F72B31 /*
> GTMNSFileManager+PathTest.m */; };
> @@ -131,6 +137,10 @@
> 0867D6A5FE840307C02AAC07 /* AppKit.framework */ = {isa =
> PBXFileReference; lastKnownFileType = wrapper.framework; name =
> AppKit.framework; path = /System/Library/Frameworks/AppKit.framework;
> sourceTree = "<absolute>"; };
> 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework */ = {isa =
> PBXFileReference; lastKnownFileType = wrapper.framework; name =
> Cocoa.framework; path = /System/Library/Frameworks/Cocoa.framework;
> sourceTree = "<absolute>"; };
> 32DBCF5E0370ADEE00C91783 /* GTM_Prefix.pch */ = {isa =
> PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.h; path = GTM_Prefix.pch; sourceTree = "<group>"; };
> + 8B2A9B1D0D8270DA00599386 /* GTMNSWorkspace+ScreenSaver.m
> */ = {isa
> = PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.objc; path = "GTMNSWorkspace+ScreenSaver.m"; sourceTree =
> "<group>"; };
> + 8B2A9B1E0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaverTest.m */ =
> {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.objc; path = "GTMNSWorkspace+ScreenSaverTest.m";
> sourceTree = "<group>"; };
> + 8B2A9B1F0D8270DA00599386 /* GTMNSWorkspace+ScreenSaver.h
> */ = {isa
> = PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.h; path = "GTMNSWorkspace+ScreenSaver.h"; sourceTree =
> "<group>"; };
> + 8B2A9BEB0D82714A00599386 /* ScreenSaver.framework */ =
> {isa =
> PBXFileReference; lastKnownFileType = wrapper.framework; name =
> ScreenSaver.framework; path = /System/Library/Frameworks/
> ScreenSaver.framework; sourceTree = "<absolute>"; };
> F413908C0D75F63C00F72B31 /* GTMNSFileManager+Path.h */ =
> {isa =
> PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.h; path = "GTMNSFileManager+Path.h"; sourceTree =
> "<group>"; };
> F413908D0D75F63C00F72B31 /* GTMNSFileManager+Path.m */ =
> {isa =
> PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.objc; path = "GTMNSFileManager+Path.m"; sourceTree =
> "<group>"; };
> F413908E0D75F63C00F72B31 /* GTMNSFileManager+PathTest.m */
> = {isa
> = PBXFileReference; fileEncoding = 4; lastKnownFileType =
> sourcecode.c.objc; path = "GTMNSFileManager+PathTest.m"; sourceTree =
> "<group>"; };
> @@ -232,6 +242,7 @@
> F42E095E0D199BD600D5DDE0 /* Cocoa.frameworkin Frameworks */,
> F42E09AE0D19A62F00D5DDE0 /*
> Carbon.framework in Frameworks */,
> F43E4F6D0D4E60C50041161F /* libz.dylib in
> Frameworks */,
> + 8B2A9BEC0D82714A00599386 /*
> ScreenSaver.framework in Frameworks */,
> );
> runOnlyForDeploymentPostprocessing = 0;
> };
> @@ -242,6 +253,7 @@
> F42E08610D199A2B00D5DDE0 /* Cocoa.frameworkin Frameworks */,
> F42E087F0D199AB400D5DDE0 /* GTM.frameworkin Frameworks */,
> F42E089C0D199B1800D5DDE0 /*
> SenTestingKit.framework in
> Frameworks */,
> + 8B2A9BED0D82714A00599386 /*
> ScreenSaver.framework in Frameworks */,
> );
> runOnlyForDeploymentPostprocessing = 0;
> };
> @@ -279,6 +291,7 @@
> 0867D69AFE84028FC02AAC07 /* External Frameworks and
> Libraries */ = {
> isa = PBXGroup;
> children = (
> + 8B2A9BEB0D82714A00599386 /*
> ScreenSaver.framework */,
> 0867D6A5FE840307C02AAC07 /*
> AppKit.framework */,
> F42E09AD0D19A62F00D5DDE0 /*
> Carbon.framework */,
> 1058C7B1FEA5585E11CA2CBB /* Cocoa.framework*/,
> @@ -333,6 +346,9 @@
> F47F1CAD0D4910FD00925B8F /*
> GTMNSColor+Theme.m */,
> F47F1CAE0D4910FD00925B8F /*
> GTMNSColor+ThemeTest.m */,
> F47F1C740D490E5C00925B8F /* GTMShading.h*/,
> + 8B2A9B1D0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.m */,
> + 8B2A9B1E0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaverTest.m */,
> + 8B2A9B1F0D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.h */,
> F42E09A80D19A5E300D5DDE0 /*
> GTMNSWorkspace+Theme.h */,
> F42E09A90D19A5E300D5DDE0 /*
> GTMNSWorkspace+Theme.m */,
> F42E0B090D19A6FB00D5DDE0 /*
> GTMNSWorkspace+ThemeTest.m */,
> @@ -416,6 +432,7 @@
> F437F55D0D50BC0A00F5C3A4 /* GTMRegex.h in
> Headers */,
> F47A79880D746EE9002302AB /*
> GTMScriptRunner.h in Headers */,
> F413908F0D75F63C00F72B31 /*
> GTMNSFileManager+Path.h in Headers */,
> + 8B2A9B220D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.h in
> Headers */,
> );
> runOnlyForDeploymentPostprocessing = 0;
> };
> @@ -594,6 +611,7 @@
> F437F55E0D50BC0A00F5C3A4 /* GTMRegex.m in
> Sources */,
> F47A79890D746EE9002302AB /*
> GTMScriptRunner.m in Sources */,
> F41390900D75F63C00F72B31 /*
> GTMNSFileManager+Path.m in Sources */,
> + 8B2A9B200D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.m in
> Sources */,
> );
> runOnlyForDeploymentPostprocessing = 0;
> };
> @@ -612,6 +630,8 @@
> F47F1CB60D49110900925B8F /*
> GTMNSColor+ThemeTest.m in Sources */,
> F43E447F0D4918BC0041161F /*
> GTMLinearRGBShadingTest.m in Sources
> */,
> F43E4E660D4E5ED40041161F /*
> GTMNSData+zlibTest.m in Sources */,
> + 8B2A9B230D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaver.m in
> Sources */,
> + 8B2A9B240D8270DA00599386 /*
> GTMNSWorkspace+ScreenSaverTest.m in
> Sources */,
> );
> runOnlyForDeploymentPostprocessing = 0;
> };
> Index: ReleaseNotes.txt
> ===================================================================
> --- ReleaseNotes.txt (revision 12)
> +++ ReleaseNotes.txt (working copy)
> @@ -24,6 +24,7 @@
> - Added GTMNSFileManager+Path for two small helpers.
> +- Added GTMNSWorkspace+ScreenSaver
> Release 1.0.0
> 14-January-2008
> Index: AppKit/GTMNSWorkspace+ScreenSaver.h
> ===================================================================
> --- AppKit/GTMNSWorkspace+ScreenSaver.h (revision 0)
> +++ AppKit/GTMNSWorkspace+ScreenSaver.h (revision 0)
> @@ -0,0 +1,33 @@
> +//
> +// GTMNSWorkspace+ScreenSaver.h
> +//
> +// Category for seeing if the screen saver is running.
> +// Requires linkage with the ScreenSaver.framework. Warning, uses some
> +// undocumented methods in the ScreenSaver.framework.
> +//
> +// Copyright 2006-2008 Google Inc.
> +//
> +// Licensed under the Apache License, Version 2.0 (the "License");
> you may not
> +// use this file except in compliance with the License. You may
> obtain a copy
> +// of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> WITHOUT
> +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> See the
> +// License for the specific language governing permissions and
> limitations under
> +// the License.
> +//
> +
> +#import <Cocoa/Cocoa.h>
> +
> +@interface NSWorkspace (GTMScreenSaverAddition)
> +
> +// Check if the screen saver is running.
> +// Returns YES if it is running.
> +// Requires linking to the ScreenSaver.framework.
> ++ (BOOL)gtm_isScreenSaverActive;
> +
> +@end
> +
> Index: AppKit/GTMNSWorkspace+ScreenSaverTest.m
> ===================================================================
> --- AppKit/GTMNSWorkspace+ScreenSaverTest.m (revision 0)
> +++ AppKit/GTMNSWorkspace+ScreenSaverTest.m (revision 0)
> @@ -0,0 +1,33 @@
> +//
> +// GTMNSWorkspace+ScreenSaverTest.m
> +//
> +// Copyright 2006-2008 Google Inc.
> +//
> +// Licensed under the Apache License, Version 2.0 (the "License");
> you may not
> +// use this file except in compliance with the License. You may
> obtain a copy
> +// of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> WITHOUT
> +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> See the
> +// License for the specific language governing permissions and
> limitations under
> +// the License.
> +//
> +#import <SenTestingKit/SenTestingKit.h>
> +#import "GTMNSWorkspace+ScreenSaver.h"
> +
> +@interface GTMNSWorkspace_ScreenSaverTest : SenTestCase
> +@end
> +
> +
> +@implementation GTMNSWorkspace_ScreenSaverTest
> +
> +- (void)testIsScreenSaverActive {
> + // Not much of a test, just executes the code. Couldn't think of a
> + // good way of verifying this one.
> + [NSWorkspace gtm_isScreenSaverActive];
> +}
> +
> +@end
> Index: AppKit/GTMNSWorkspace+ScreenSaver.m
> ===================================================================
> --- AppKit/GTMNSWorkspace+ScreenSaver.m (revision 0)
> +++ AppKit/GTMNSWorkspace+ScreenSaver.m (revision 0)
> @@ -0,0 +1,125 @@
> +//
> +// GTMNSWorkspace+ScreenSaver.m
> +//
> +// Copyright 2006-2008 Google Inc.
> +//
> +// Licensed under the Apache License, Version 2.0 (the "License");
> you may not
> +// use this file except in compliance with the License. You may
> obtain a copy
> +// of the License at
> +//
> +// http://www.apache.org/licenses/LICENSE-2.0
> +//
> +// Unless required by applicable law or agreed to in writing, software
> +// distributed under the License is distributed on an "AS IS" BASIS,
> WITHOUT
> +// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> See the
> +// License for the specific language governing permissions and
> limitations under
> +// the License.
> +//
> +
> +#import <Carbon/Carbon.h>
> +#import <ScreenSaver/ScreenSaver.h>
> +#import "GTMNSWorkspace+ScreenSaver.h"
> +
> +// Interesting class descriptions extracted from
> ScreenSaver.framework using
> +// class-dump. Note that these are "not documented".
> +
> +@protocol ScreenSaverControl
> +
> +- (BOOL)screenSaverIsRunning;
> +- (BOOL)screenSaverCanRun;
> +- (void)setScreenSaverCanRun:(BOOL)fp8;
> +- (void)screenSaverStartNow;
> +- (void)screenSaverStopNow;
> +- (void)restartForUser:(id)fp8;
> +- (double)screenSaverTimeRemaining;
> +- (void)screenSaverDidFade;
> +- (BOOL)screenSaverIsRunningInBackground;
> +- (void)screenSaverDidFadeInBackground:(BOOL)fp8
> + psnHi:(unsigned int)fp12
> + psnLow:(unsigned int)fp16;
> +
> +@end
> +
> +@interface ScreenSaverController : NSObject <ScreenSaverControl> {
> + NSConnection *_connection;
> + id _daemonProxy;
> + void *_reserved;
> +}
> +
> ++ (id)controller;
> ++ (id)monitor;
> ++ (id)daemonConnectionName;
> ++ (id)enginePath;
> +- (void)_connectionClosed:(id)fp8;
> +- (id)init;
> +- (void)dealloc;
> +- (BOOL)screenSaverIsRunning;
> +- (BOOL)screenSaverCanRun;
> +- (void)setScreenSaverCanRun:(BOOL)fp8;
> +- (void)screenSaverStartNow;
> +- (void)screenSaverStopNow;
> +- (void)restartForUser:(id)fp8;
> +- (double)screenSaverTimeRemaining;
> +- (void)screenSaverDidFade;
> +- (BOOL)screenSaverIsRunningInBackground;
> +- (void)screenSaverDidFadeInBackground:(BOOL)fp8
> + psnHi:(unsigned int)fp12
> + psnLow:(unsigned int)fp16;
> +
> +@end
> +
> +// end of extraction
> +
> +@implementation NSWorkspace (GTMScreenSaverAddition)
> +// Check if the screen saver is running.
> ++ (BOOL)gtm_isScreenSaverActive {
> + BOOL answer = NO;
> + ScreenSaverController *controller = nil;
> + // We're calling into an "undocumented" framework here, so we are
> going to
> + // step rather carefully.
> +
> + Class screenSaverControllerClass =
> NSClassFromString(@"ScreenSaverController");
> + NSAssert(screenSaverControllerClass,
> + @"Are you linked with ScreenSaver.framework?"
> + " Can't find ScreenSaverController class.");
> + if ([screenSaverControllerClass
> respondsToSelector:@selector(controller)]) {
> + controller = [ScreenSaverController controller];
> + if (controller) {
> + if ([controller
> respondsToSelector:@selector(screenSaverIsRunning)]) {
> + answer = [controller screenSaverIsRunning];
> + } else {
> + NSLog(@"ScreenSaverController no longer supports -
> screenSaverIsRunning?");
> + }
> + }
> + }
> +
> + if (!controller) {
> + // If we can't get the controller, chances are we are being run
> from the
> + // command line and don't have access to the window server. As
> such we are
> + // going to fallback to the older method of figuring out if a
> screen saver
> + // is running.
> + ProcessSerialNumber psn;
> + // Check if the saver is already running
> + require_noerr(GetFrontProcess(&psn), CantGetFrontProcess);
> +
> + CFDictionaryRef cfProcessInfo
> + = ProcessInformationCopyDictionary(&psn,
> +
> kProcessDictionaryIncludeAllInformationMask);
> +
> + require(cfProcessInfo, CantGetFrontProcessInfo);
> +
> + NSString *bundlePath = [(NSDictionary*)cfProcessInfo
> objectForKey:@"BundlePath"];
> +
> + // ScreenSaverEngine is the frontmost app if the screen saver is
> actually
> + // running Security Agent is the frontmost app if the "enter
> password"
> + // dialog is showing
> + answer = [bundlePath hasSuffix:@"ScreenSaverEngine.app"] ||
> + [bundlePath hasSuffix:@"SecurityAgent.app"];
> + CFRelease(cfProcessInfo);
> + }
> +CantGetFrontProcessInfo:
> +CantGetFrontProcess:
> + return answer;
> +}
> +
> +@end