Is there a way I test to see if Firefox windows are hidden in OS X via the "Hide Firefox" (Command-H) option? Enumerating using nsIWindowMediator says that the hidden attribute is false and the windowState is STATE_NORMAL for these hidden windows in OS X. Thanks!
Try console.log(window) or if you dont have access to thew indow object Services.appShell.hiddenDOMWindow.console.log(Services.wm.getMostRecentWindow('navigator:browser')) then in browser console go and click '[object ChromeWindow]' and then it will print all its enumerable and non-enumerable properties.
Maybe it will show something in here differently when it's hidden I'm not sure.
i dont know but heres a way that might help you figure out.
install this addon from github
and then in scratchpad in browser environment run Cu.import('chrome://cdumpjsm/content/cDump.jsm'); cDump(window,{depth:0}) when hidden, then save that file. then show the window then run cDump again, then diff the files
Ok at long last here is your solution. js-ctypes using objective-c:
Tested on OS 10.9
GitHubGIST :: Noitidart / _ff-addon-snippet-OSXHidden.js
Cu.import('resource://gre/modules/ctypes.jsm');
var objc = ctypes.open(ctypes.libraryName('objc'));
// types
var id = ctypes.voidptr_t;
var SEL = ctypes.voidptr_t;
var BOOL = ctypes.signed_char;
// constants
var nil = ctypes.voidptr_t(0);
//common functions
var objc_getClass = objc.declare('objc_getClass', ctypes.default_abi, id, ctypes.char.ptr);
var sel_registerName = objc.declare('sel_registerName', ctypes.default_abi, SEL, ctypes.char.ptr);
var objc_msgSend = objc.declare('objc_msgSend', ctypes.default_abi, id, id, SEL, '...');
//common selectors
var alloc = sel_registerName('alloc');
var init = sel_registerName('init');
var release = sel_registerName('release');
//now using docs here: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/index.html#//apple_ref/occ/instp/NSApplication/hidden
// pool = [[NSAutoreleasePool alloc] init]
var NSAutoreleasePool = objc_getClass('NSAutoreleasePool');
var pool = objc_msgSend(objc_msgSend(NSAutoreleasePool, alloc), init);
// NSApp = [NSApplication sharedApplication];
var NSApplication = objc_getClass('NSApplication');
var sharedApplication = sel_registerName('sharedApplication');
var NSApp = objc_msgSend(NSApplication, sharedApplication);
// [NSApp isHidden]
var isHidden = sel_registerName('isHidden');
var objc_msgSend_returnBool = objc.declare('objc_msgSend', ctypes.default_abi, BOOL, id, SEL, '...'); //this is return value because `isHidden` returns a BOOL per the docs
var rez_isHidden = objc_msgSend_returnBool(NSApp, isHidden);
console.info('rez_isHidden:', rez_isHidden, rez_isHidden.toString(), uneval(rez_isHidden));
if (rez_isHidden == 0) {
console.log('Firefox is HIDDEN!');
} else if (rez_isHidden == 1) {
console.log('Firefox is showing.');
} else {
console.warn('rez_isHidden was not 0 or 1, this should never happen, if it did, objc should error and crash the browser');
}
// [pool release]
objc_msgSend(pool, release);
objc.close();
Credit to #arai for teaching me objc jsctypes! When no one else would the guy spoon fed me!!! More people should spoon feed each other!
Related
Is there a property on the AVAudioPlayer class that I can use to get the samples? If not is there another class I can use to get this information?
Here's what I have:
var openDialog = NSOpenPanel.OpenPanel;
openDialog.CanChooseFiles = true;
openDialog.CanChooseDirectories = false;
openDialog.AllowedFileTypes = new string[] { "wav" };
if (openDialog.RunModal() == 1)
{
var url = openDialog.Urls[0];
if (url != null)
{
var path = url.Path;
var audioplayer = AVFoundation.AVAudioPlayer.FromUrl(file);
var samples = audioplayer.SAMPLES?;
Visual Studio Mac (C# / Xamarin)
AVAudioPlayer does not give you access to the sample data, but if you switch playback to AVPlayer you can use an MTAudioProcessingTap to "tap" the samples as they are played.
If you simply want to examine the samples in your file you can use AVAudioFile.
// get the total number of samples
var audioFile = new AVAudioFile(file, out outError);
var samples = audioFile.Length;
We are porting from iOS to macOS and need to be able to print PDF documents directly from the app. Below is the relevant method.
Just don't see how to define the "contextInfo" as the PDFDocument?
- (void)printDocumentWithSettings:(NSDictionary<NSPrintInfoAttributeKey, id> *)printSettings
showPrintPanel:(BOOL)showPrintPanel
delegate:(id)delegate
didPrintSelector:(SEL)didPrintSelector
contextInfo:(void *)contextInfo;
PDFDocument *pdfDoc = [[PDFDocument alloc] initWithURL:url];
Sending our user to the AdobePDF viewer to search through the system folders is not a solution. As is typical the Apple Doc is not helpful and many of the macOS samples are up to eight years old!
Any help or alternate solution would be appreciated.
Thanks,
John
Apologies for using Swift, but this is the approach I've taken for printing PDF.
PDFDocument has a method to create an NSPrintOperation.
if let printOperation = thePDFDocument?.printOperation(for: thePrintInfo(), scalingMode: .pageScaleNone, autoRotate: true){
printOperation.printPanel = thePrintPanel()
/// Would prefer to use .runModal but don't know what the window is.
printOperation.run()
}
thePrintInfo() and thePrintPanel() are functions that define the print settings and dialog.
func thePrintInfo() -> NSPrintInfo {
let thePrintInfo = NSPrintInfo()
thePrintInfo.horizontalPagination = .fit
thePrintInfo.verticalPagination = .fit
thePrintInfo.isHorizontallyCentered = true
thePrintInfo.isVerticallyCentered = true
thePrintInfo.leftMargin = 0.0
thePrintInfo.rightMargin = 0.0
thePrintInfo.topMargin = 0.0
thePrintInfo.bottomMargin = 0.0
thePrintInfo.jobDisposition = .spool
return thePrintInfo
}
// Add the Page Setup options to the Print Dialog
func thePrintPanel() -> NSPrintPanel {
let thePrintPanel = NSPrintPanel()
thePrintPanel.options = [
NSPrintPanel.Options.showsCopies,
NSPrintPanel.Options.showsPrintSelection,
NSPrintPanel.Options.showsPageSetupAccessory,
NSPrintPanel.Options.showsPreview
]
return thePrintPanel
}
This can be accomplished by:
Creating a pdfView.
#property (weak) IBOutlet PDFView *showPDFView;
Assigning the URL of your PDF and setting the view to this document.
pdfDoc = [[PDFDocument alloc] initWithURL:url];
[showPDFView setDocument:pdfDoc];
Calling the print method on the view.
[showPDFView print : nil];
That's all there is to it!
I'm trying to programmatically change the configured screen saver.
If I do
$ defaults -currentHost read com.apple.screensaver
{
CleanExit = YES;
PrefsVersion = 100;
idleTime = 600;
moduleDict = {
moduleName = XXXX;
path = "/Users/juanjo/Library/Screen Savers/XXXX.saver";
type = 0;
};
showClock = 0;
}
I can see that info or even update it using the write parameter.
This settings are not accesibles via NSUserDefaults but they are via CF.
I was able to do this by code
var moduleDict = CFPreferencesCopyAppValue("moduleDict", "com.apple.screensaver") as CFDictionary
but when I try to get one value from that "dict" the program crash in this line:
var saverName = CFDictionaryGetValue(moduleDict, "moduleName")
saying EXC_BAD_ACCESS (code=EXC_I386_GPFLT).
So, do you know how can I read this values and write back?
As I mentioned in Cocoa-Dev list, I was able to do it this way.
Reading:
var moduleDict = CFPreferencesCopyAppValue("moduleDict", "com.apple.screensaver") as NSDictionary
var saverName = moduleDict["moduleName"] as String!
Writing:
var moduleDict = CFPreferencesCopyAppValue("moduleDict", "com.apple.screensaver") as NSDictionary
var mutable = moduleDict.mutableCopy() as NSMutableDictionary
mutable["moduleName"] = "MyScreenSaver"
mutable["path"] = mySaverPath
CFPreferencesSetValue("moduleDict", mutable as CFPropertyList, "com.apple.screensaver", kCFPreferencesCurrentUser, kCFPreferencesCurrentHost)
CFPreferencesAppSynchronize("com.apple.screensaver")
I have a status-menu app that can be started using a system wide shortcut. When the app gets active, it would be great if I could somehow get the text that is selected in the currently running application.
So for example I type something in my text-editor, select the text, hit my global shortcut, my app comes up and I would now love to know the selected text from the text-editor.
What I have so far is the following (adopted code from How to get global screen coordinates of currently selected text via Accessibility APIs.)
AXUIElementRef systemWideElement = AXUIElementCreateSystemWide();
AXUIElementRef focussedElement = NULL;
AXError error = AXUIElementCopyAttributeValue(systemWideElement, kAXFocusedUIElementAttribute, (CFTypeRef *)&focussedElement);
if (error != kAXErrorSuccess) {
NSLog(#"Could not get focussed element");
} else {
AXValueRef selectedTextValue = NULL;
AXError getSelectedTextError = AXUIElementCopyAttributeValue(focussedElement, kAXSelectedTextAttribute, (CFTypeRef *)&selectedTextValue);
if (getSelectedTextError == kAXErrorSuccess) {
selectedText = (__bridge NSString *)(selectedTextValue);
NSLog(#"%#", selectedText);
} else {
NSLog(#"Could not get selected text");
}
}
if (focussedElement != NULL) CFRelease(focussedElement);
CFRelease(systemWideElement);
The problem here is that it does not work with apps like Safari and Mail...
Thanks
This is actually very easy, kAXSelectedTextAttribute is your friend.
extension AXUIElement {
var selectedText: String? {
rawValue(for: kAXSelectedTextAttribute) as? String
}
func rawValue(for attribute: String) -> AnyObject? {
var rawValue: AnyObject?
let error = AXUIElementCopyAttributeValue(self, attribute as CFString, &rawValue)
return error == .success ? rawValue : nil
}
}
This is not technically a solution to your exact question because the user would have to trigger this from the Services menu rather than it simply happening when they trigger your menu bar app.
You could use a System Service. You create a service for your app that sends the currently selected text to your menu bar app via a Pasteboard.
I'm working on an app that has a reminder component. I'm using Calendar Store to get a list of calendars, and I want the user to choose which calendar they'd like to add a task to. The problem is, CalCalendar seems not to distinguish between event calendars and task calendars.
NSArray* calendars = [[CalCalendarStore defaultCalendarStore] calendars];
for( CalCalendar* aCalendar in calendars ) {
if( aCalendar.isEditable ) {
NSLog( #"editable calendar: %#", aCalendar );
}
}
This outputs:
editable calendar: CalCalendar <0x6e04d10> {UID = 8AA8FFAD-D781-47F7-9231-CF66E1753983; title = Work; notes = (null); color = NSCalibratedRGBColorSpace 0.054902 0.380392 0.72549 1; type = CalDAV; editable = 1}
editable calendar: CalCalendar <0x6e05000> {UID = A7F4A1B2-D1CF-4A20-9F84-CD1A1E99773E; title = Home; notes = ; color = NSCalibratedRGBColorSpace 0.72549 0.054902 0.156863 1; type = CalDAV; editable = 1}
editable calendar: CalCalendar <0x6e050f0> {UID = 43B14D2A-9976-461C-8EFE-5FA029381828; title = Personal; notes = (null); color = NSCalibratedRGBColorSpace 0.901961 0.784314 0 1; type = CalDAV; editable = 1}
editable calendar: CalCalendar <0x6e05140> {UID = F42EC365-20AC-4251-B45E-FB7F169928F0; title = Mac; notes = (null); color = NSCalibratedRGBColorSpace 0.054902 0.380392 0.72549 1; type = Local; editable = 1}
editable calendar: CalCalendar <0x6e05190> {UID = FF771FF9-3969-4001-BBA4-9B7B00E80291; title = Cloud 2; notes = (null); color = NSCalibratedRGBColorSpace 0.054902 0.380392 0.72549 1; type = CalDAV; editable = 1}
editable calendar: CalCalendar <0x6e051e0> {UID = 40234537-869C-4CC2-89B9-DD4F7D36C169; title = Groceries; notes = ; color = NSCalibratedRGBColorSpace 0.443137 0.101961 0.462745 1; type = CalDAV; editable = 1}
I know that the first 2 are event calendars, and the last 4 are task lists. And, iCal definitely knows the difference, because it shows only event calendars for events, and task calendars for tasks.
But there appears to be no way via the Calendar Store APIs to determine this programmatically, unless I'm missing something.
Update: I see I'm not the only one to notice this, as I found rdar://10377730. I've just filed my own report, as rdar://10980542
I'm not super happy with it, but the workaround I'm using now is to simply try to create a task in each calendar. If you try to create a task in an event calendar, you'll get an error. It looks a little something like:
- (BOOL) isCalendarAUsableTaskList:(CalCalendar*)aCalendar
{
if( !aCalendar.isEditable ) return NO;
// Try to make a task here.
CalTask* newTask = [CalTask task];
newTask.calendar = aCalendar;
newTask.title = #"Test Item";
NSError* anError = nil;
if( ![[CalCalendarStore defaultCalendarStore] saveTask:newTask error:&anError] ) {
// Couldn't make a task, this calendar is no bueno.
NSLog( #"Error saving task to calendar %# (%#)", aCalendar.title, [anError localizedDescription] );
return NO;
}
// Created a task. Now clean up on our way out.
NSLog( #"Saved task to calendar %#", aCalendar.title );
[[CalCalendarStore defaultCalendarStore] removeTask:newTask error:nil];
return YES;
}