I want to use applescript to get the window of an application, but since the app can have several windows, I use objc to get windowId like follow:
CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly |
kCGWindowListExcludeDesktopElements,
kCGNullWindowID);
for (CFIndex i = 0; i < windowListCount; i++) {
CFDictionaryRef windowInfo = (CFDictionaryRef)CFArrayGetValueAtIndex(windowList, i);
CGWindowID windowId;
CFNumberGetValue((CFNumberRef)CFDictionaryGetValue(windowInfo, kCGWindowNumber), kCGWindowIDCFNumberType, &windowId);
}
but this windowId is different from the windowId I get from the appleScript like follow:
tell application "/Applications/QQBrowser.app"
repeat with theWindow in windows
if visible of theWindow is true then
get id of theWindow
end if
end repeat
end tell
I did not find sth useful, does anybody know why?
my destination is to distinguish the windows of an app, does anybody have some ideas?
Thanks very much~
tell application "Numbers"
get id of every window whose visible is true
end tell
Result: {1462, 1439}
These are unique id's for the open visible windows. You could use this unique id to distinguish windows in an app, and you can also get more information about each window with code like:
get properties of window id 1462
Related
I want to create a scoring system. I have 4 buttons with 4 different but similar scripts and want to share 1 GUI Text for the scores. Example Code:
var something : Sprite;
var SpriteRenderer : SpriteRenderer;
var score : int = 0;
var guiScore : GUIText;
function OnMouseDown () {
if(SpriteRenderer.sprite == something) {
score += 1;
guiScore.text = "Score: " = score;
}
}
Right now, if I pressed a button and got a point then I pressed a different button the score would start from 0 again. How can I share data something like static variables but different scripts? I know this sounds a bit noobie but any help would be much appreciated. Thanks in advance
Static variables won't appear in the inspector so you can't assign the GUIText in the inspector (thanks for making me find out). So try using GetComponent instead:
// make a variable of type GUIText
var guiScore: GUIText;
// assign the gameobject in the inspector
var staticObject: GameObject;
// Again I don't know the name of your script, so I'll name it StaticScript
// get the script
StaticScript scr = staticObject.GetComponent(StaticScript);
// assign local GUIText with the one from above
guiScore = scr.guiScore;
This way you have already shared 1 GUIText for all other scripts.
However you said:
Right now, if I pressed a button and got a point then I pressed a
different button the score would start from 0 again
Doesn't that mean something is wrong with the score, not the GUIText?
I am new to programming for Mac, so forgive me if my question is too silly.
I am writing a small application, where I need to set a destination folder.
I think, instead of just using a NSButton "Choose folder", the approach that Firefox or Safari with their "Save as..." dialogs take is a very user friendly one.
Using a NSPopUpButton, where one can pick a folder from the user's favorites, or from the last used folders. Additionally I would add a top-most entry "Choose...", what would open a NSOpenPanel.
My question is: How can I get the user's favorite folders, that are shown e.g. in the Finder application, and populate my NSPopUpButton with them?
Here how it looks like in Firefox:
You can find the relevant functions inside the Application Services framework, and you can get the list of items like this:
LSSharedFileListRef favorites = LSSharedFileListCreate(NULL, kLSSharedFileListFavoriteItems, NULL);
CFArrayRef snapshot = LSSharedFileListCopySnapshot(favorites, NULL);
CFIndex snapshotCount = CFArrayGetCount(snapshot);
for (CFIndex i = 0; i < snapshotCount; ++i) {
LSSharedFileListItemRef item = (LSSharedFileListItemRef)CFArrayGetValueAtIndex(snapshot, i);
CFURLRef itemURL = NULL;
LSSharedFileListItemResolve(item, kLSSharedFileListNoUserInteraction | kLSSharedFileListDoNotMountVolumes, &itemURL, NULL);
NSLog(#"%#", itemURL);
if (itemURL != NULL) {
CFRelease(itemURL);
}
}
CFRelease(snapshot);
CFRelease(favorites);
When I run this on my computer, I get:
nwnode://domain-AirDrop
file://localhost/Applications/
file://localhost/System/Library/CoreServices/Finder.app/Contents/Resources/MyLibraries/myDocuments.cannedSearch/
file://localhost/Users/dave/
file://localhost/Users/dave/Desktop/
file://localhost/Users/dave/Developer/
file://localhost/Users/dave/Documents/
file://localhost/Users/dave/Downloads/
file://localhost/Users/dave/Dropbox/
Which corresponds to:
I am working on an application that moves windows of third party applications around on the screen.
To get an overview of all currently open windows, I use
CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
This returns an array of dictionaries defining every open window.
Here's an exemplary dictionary returned:
{
kCGWindowAlpha = 1;
kCGWindowBounds = {
Height = 442;
Width = 475;
X = 3123;
Y = "-118";
};
kCGWindowIsOnscreen = 1;
kCGWindowLayer = 0;
kCGWindowMemoryUsage = 907184;
kCGWindowName = Untitled;
kCGWindowNumber = 7328;
kCGWindowOwnerName = TextEdit;
kCGWindowOwnerPID = 20706;
kCGWindowSharingState = 1;
kCGWindowStoreType = 2;
kCGWindowWorkspace = 3;
},
The dictionary is full of good information used elsewhere but lacks an accessibility object that could be used to modify the windows' positions. Windows are clearly identified by the Window Number.
I am now using the PID (kCGWindowOwnerPID) to create an accessibility object for the window's application:
AXUIElementRef app = AXUIElementCreateApplication(pid);
Followed by retrieving a list of all windows the application has opened using AXUIElementCopyAttributeValues:
NSArray *result;
AXUIElementCopyAttributeValues(
(AXUIElementRef) app,
kAXWindowsAttribute,
0,
99999,
(CFArrayRef *) &result
);
This works and returns an array of AXUIElements.
This is where I am stuck. There seems to be no API call to retrieve the Window Number of an accessibility object. Is there any way to either
a) Find the accessibility object's Window Number (to ultimately iterate over the array and find the right window)
or
b) Otherwise clearly match a window described in the array returned by CGWindowListCopyWindowInfo to the Accessibility Objects returned by AXUIElementCopyAttributeValues?
We ended up hiring a dedicated Accessibility Developer for this task.
It turns out there is no way to do this without using undocumented APIs (a no go in our case).
Luckily, there is a practical workaround:
Loop over all open windows of the app. Get their position, size and title:
AXUIElementCopyAttributeValue(target, kAXPositionAttribute, (CFTypeRef*)&posValue);
AXUIElementCopyAttributeValue(target, kAXSizeAttribute, (CFTypeRef*)&sizeValue);
AXUIElementCopyAttributeValue(target, kAXTitleAttribute, (CFTypeRef*)&titleValue);
Next, convert the position and size into actual CGPoint and CGSize values:
AXValueGetValue(posValue, kAXValueCGPointType, &point);
AXValueGetValue(sizeValue, kAXValueCGSizeType, &size);
Compare the size, position and title against the values returned by the object in CGWindowListCopyWindowInfo().
If they match, you can safely assume it's the window you were looking for and use the already open AXUIElement (target in our case) to work it.
The overhead for looping through all open windows turns out to be negligible on OSX. There is a pretty low cap on how many windows are open at the same time.
Also, while this is not 100% accurate (it is possible that 2 windows have the same position, size and title), we haven't encountered any situation in real usage where this happens so far.
There is a private function for obtaining CG window number for a given AX object for window: _AXUIElementGetWindow .
More details in SO discussion Uniquely identify active window on OS X
It looks like there is no public API to do the task with 100% probability. Identifying windows by title and frame (as described in answer above) will works in 99.9% of cases.
Clarifying other answers that suggest the undocumented call of _AXUIElementGetWindow.
In Swift, do this:
1. Create Bridged-Header.h with the following contents:
#import <AppKit/AppKit.h>
AXError _AXUIElementGetWindow(AXUIElementRef element, uint32_t *identifier);
2. Reference this file in your build settings: (your path may vary, it is relative to project root)
3. Call like this:
// variable 'window' is your AXUIElement window
var cgWindowId = CGWindowID()
if (_AXUIElementGetWindow(window, &gcWindowId) != .success) {.
print("cannot get CGWindow id (objc bridged call)")
}
Congrats, you succesfully called objective C functions via a bridge!
I am writing a program that needs to set a window just above/below the traybar for gtk. I have tried using the 2 approaches that failed. One was using the gtk_status_icon_position_menu function and placing the window in the point where the user clicks (in the tray bar). The problem is that these solutions work in gnome(Linux) but not in Windows. In Linux they work because the window manager doesn't seem to allow placement of windows in the tray panel, honoring the closest possible. In Windows this doesn't happen and the window can go "out" of the screen which understandably is not desired.
With this said i went out for a work around. My idea was to set the window in the location of mouse click and get the x and y coordinates of a normal window placement and with it's size check if it would be within the screen boundaries. If it was not make the correction. I have came up with the functions needed but for some reason the gdk_drawable_get_size(window->window ,&WindowWidth, &WindowHeight) and other similar functions only give the correct size value after the second run of the signal function. The result of the first run is just 1 to both size and width. (I have read the issue of X11 not giving correct results, but i think this is not it)
event_button = (GdkEventButton *) event;
if (event_button->button == 1)
{
if (active == 0)
{
gboolean dummy;
gint WindowHeight, WindowWidth, WindowPosition[2];
GdkScreen *screen;
gint ScreenHeight, ScreenWidth;
dummy = FALSE;
gtk_widget_show_all(window);
gtk_window_present(GTK_WINDOW(window));
gtk_status_icon_position_menu(menu, &pos[X], &pos[Y], &dummy, statusicon);
gtk_window_move(GTK_WINDOW(window), pos[X],pos[Y]);
gdk_drawable_get_size(window->window ,&WindowWidth, &WindowHeight);
screen = gtk_status_icon_get_screen(statusicon);
ScreenWidth = gdk_screen_get_width(screen);
ScreenHeight = gdk_screen_get_height(screen);
g_print("Screen: %d, %d\nGeometry: %d, %d\n",ScreenWidth, ScreenHeight, WindowWidth, window->allocation.height);
gtk_entry_set_text(GTK_ENTRY(entry),"");
active = 1;
return TRUE;
}
How can i do what i want in a portable way?
I think gtk_status_icon_position_menu should work fine, as i used it for the same purpose.
Are you trying this stuff with X11, What is the actual result you are getting.
I have an MFC MDI Application and I am trying to implement Automation with it. I am trying to create a RemoveDocument. How is that done? OnCloseDocument is causing problems. Is there a "standard" for doing that?
You could just send a WM_CLOSE message to the Document's frame.
Edit: You could try sending it to the document's view instead. You can get all views that point to a given document by calling:
POSITION pos = pDoc->GetFirstViewPosition();
while( pos != NULL )
{
CView* pView = GetNextView( pos );
}
I "think" that should do the trick ...