-1

In working in Xcode 4.6.1, I want to get a list of all windows, choose a specific window (maybe by windowID) and specify its Size (width & height), and Origin (X & Y).

I can get the Screen size, NSStringFromRect allows me to view the results in NSLog. NSRect is {NSPoint origin; NSSize size;} and in context of my display {{0, 0}, {2560, 1440}}.

I use the following to get my displays Size. (Thanks to Guillaume comment regarding C structs & casting):

-(void)awakeFromNib
{
    NSRect screenRect = [[NSScreen mainScreen] frame];
    CGSize myScreenSize = screenRect.size;
    NSLog(@"myScreenSize = %d x %d", (int)myScreenSize.width, (int)myScreenSize.height);

    // returns: myScreenSize = 2560 x 1440
}
@end

I would like to try setting the Size & Origin of another launched Application window(that doesn't belong to my process).

So first I get a list of all running Applications, and a windowID for each window, then choose a Window to move/resize.

Based on other searches this could be done using CGSPrivate.h, or the Accessibility api. I don't know how to use either of these yet to SET the size etc of a specific windowID/Number or PID

#import "rsAppDelegate.h"

@implementation rsAppDelegate

-(void)awakeFromNib
{
    // get the size of the main screen
    NSRect screenRect = [[NSScreen mainScreen] frame];    
    // devrived fromGuillaume's suggestion
    CGSize myScreenSize = screenRect.size;
    CGPoint myScreenOrigin = screenRect.origin;
    NSLog(@"myScreenSize = %d x %d", (int)myScreenSize.width, (int)myScreenSize.height);
    NSLog(@"Origin = %d , %d", (int)myScreenOrigin.x, (int)myScreenOrigin.y);

    // To get a list of Application windows, the PID of the window, the window number, and the window bounds (origin, height, width)   
    CFArrayRef windowList = CGWindowListCopyWindowInfo(kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements, kCGNullWindowID);
    for (NSMutableDictionary* entry in (__bridge NSArray*)windowList)
    {
        NSArray *ownerName = [entry objectForKey:(id)kCGWindowOwnerName];
        NSInteger ownerPID = [[entry objectForKey:(id)kCGWindowOwnerPID] integerValue];
        NSInteger windowNumber = [[entry objectForKey:(id)kCGWindowNumber] integerValue];
        NSArray *ownerBounds = [entry objectForKey:(id)kCGWindowBounds];
        NSLog(@"\nApp = %@ \nAppPID = %ld \nwindowNumber = %ld \nProgramBounds = %@", ownerName, (long)ownerPID, (long)windowNumber, ownerBounds);
    }
    CFRelease(windowList);
    /*
    OUTPUT:
    myScreenSize = 2560 x 1440 | Origin = 0 , 0
    App = Xcode
    AppPID = 3260
    windowNumber = 4493
    ProgramBounds = {
        Height = 1285;
        Width = 1852;
        X = 339;
        Y = 32;
    }
    */

    // Knowing the name of the application, it's PID, window number, and bounds to a percentage of the screen:
    // Set it's origin and size

}
@end

So now I know the screen size, and have all the available info about all the windows from each application. How do I specify a NEW Origin, Width, Height of an application with PID 3260, Window Number 4493?

newPos = AXValueCreate(kAXValueCGPointType, windowOrigin);
AXUIElementSetAttributeValue(chosenWindow, kAXPositionAttribute, newPos)

newSize = AXValueCreate(kAXValueCGSizeType, windowSize);
AXUIElementSetAttributeValue(chosenWindow, kAXSizeAttribute, newSize);

How do I specify the chosenWindow ? What format do I specify windowOrigin & windowSize ?

Here is the info I've found, but I don't know how to use:

kAXValueCGPointType is a wrapper for CGPoint; see CoreGraphics.h Declared in AXValue.h

kAXValueCGSizeType is a wrapper for CGSize;

These are AXValueType wrappers for other structures. You must use the AXValueCreate and AXValueGetValue functions to convert between the wrapped structure and the native structure.

rootscript
  • 78
  • 1
  • 7
  • -update_01:I've been searching & testing, and found a working method to get and display the screen resolution, thanks to @danielpunkass thread here: [link](http://stackoverflow.com/a/864247/2128143) – rootscript Apr 16 '13 at 18:29
  • Do not. Your app has just one window and it is the size of the screen. Don't make any other windows. – matt Apr 16 '13 at 18:37
  • mainScreen frame = {{0, 79}, {2560, 1339}} 0 from the left, 79 from the top, 2560 across to the right, and 1339 down. – rootscript Apr 16 '13 at 19:27
  • Another way of looking at this is NSString* frameAsString = {{0, 79}, {2560, 1339}}. How do I extract 1339 from frameAsString? Can I use something like [[frameAsString objectAtIndex:3] intValue] ?? – rootscript Apr 17 '13 at 00:51
  • Thanks to @hermann-klecker and his float to int answer, here [link](http://stackoverflow.com/a/6969688/2128143) – rootscript Apr 17 '13 at 10:26
  • 1
    You need to learn the C language, data types, and structures. To get the size out of a `CGRect`, just type: `CGSize mySize = myRect.size;`. To convert a `float` to an `int`, use a cast, there is a no need to use a `NSNumber`: `int valueAsAnInt = (int)valueAsAFloat;` or just `int valueAsAnInt = valueAsAFloat;`. You can display a float with `NSLog()` if you use `%f` instead of `%d`. Also there is no need to use `int`s at all since all values in Quartz are `CGFloat`s. – Guillaume Apr 17 '13 at 12:55
  • @Guillaume I've read a little more about C Structures; thank you for your advice. I understand a little more now, so I can get structs origin info too: `NSRect screenRect = [[NSScreen mainScreen] frame]; CGPoint myScreenOrigin = screenRect.origin; NSLog(@"Origin = %d , %d", (int)myScreenOrigin.x, (int)myScreenOrigin.y);` – rootscript Apr 22 '13 at 10:29
  • Found this link from weichsel To get a list of window IDs and the PID of the owner [link](http://stackoverflow.com/a/2108985/2128143) – rootscript Apr 22 '13 at 11:23

1 Answers1

1

First you need to find out where your window is.

From NSWindow Class Reference ...

screen

Returns the screen the window is on.

- (NSScreen *)screen

Return Value

The screen where most of the window is on; nil when the window is offscreen.

Discussion

When the window is partly on one screen and partly on another, the screen where most of it lies is returned.

deepestScreen

Returns the deepest screen the window is on (it may be split over several screens).

- (NSScreen *)deepestScreen

Return Value

The deepest screen the window is on; nil when the window is offscreen.

Then, if, and only if your window is on one screen, can you determine its size as a percentage of something.

In general though, without constraining the window to the main screen or some user selected screen, your approach will run into problems.

Otherwise, you'll need to consider how to handle varying screen configurations.

You'll also need the following NSApplication delegate method

applicationDidChangeScreenParameters:

Sent by the default notification center when the configuration of the displays attached to > the computer is changed (either programmatically or when the user changes settings in the > Displays control panel).

- (void)applicationDidChangeScreenParameters:(NSNotification *)aNotification Parameters

aNotification A notification named NSApplicationDidChangeScreenParametersNotification. Calling the object method of this notification returns the NSApplication object itself.

NSScreen instances have a frame method that returns an NSRect just like NSWindow does. From that you can determine the appropriate height and width you want to set the size.width and size.height to use when creating an NSRect to use for setting your window's frame.

Example of getting the screen frame and accessing its height:

NSRect mainScreenFrameRect = [[NSScreen mainScreen] frame];
CGFloat screenHeight = mainScreenFrameRect.size.height;

Getting a percentage of the height or width is easy math from there.

I suggest using the NSWindow method setFrame:display:animate: in your applicationDidFinishLaunching or other appropriate place. (consider if you have an NSWindow subclass, which you might want.)

uchuugaka
  • 12,679
  • 6
  • 37
  • 55
  • Thank you for your advice regarding NSScreen; it is included in my latest progress (edit_04) above. So I can get the screen frame, and I can get the 'bounds' of all application windows. I don't know how to SET the bounds of a 'chosen' application window. – rootscript Apr 22 '13 at 20:21
  • I hadn't considered 'animating' the windows before, I was just going to set them to change immediately. Your suggestion of using `setFrame:display:animate:` would be a very nice additional. – rootscript Apr 22 '13 at 22:51
  • Maybe I'm missing something obvious here, but no one has suggested how to resize a specific Window (identified by owner, PID, or Window ID); is that because 'that part' is so easy and everyone thinks that I probably know that part already? or is it because I'm approaching the whole thing in a ridiculous way, and that there is a much easier way to do all this? – rootscript Apr 22 '13 at 23:04
  • Thanks uchuugaka - I have a question regarding `setFrame:display:animate:` Can I only use it on windows I create, or can I use it on windows belonging to other applications? – rootscript Apr 22 '13 at 23:19
  • windows your app owns. To impact other applications' windows, you'll need to use something else entirely. You'll need either the Accessibility APIs or AppleScript (or NSAppleScript or OSA scripting) or some combination, as far as I know.http://stackoverflow.com/questions/4231110/how-can-i-move-resize-windows-programmatically-from-another-application – uchuugaka Apr 23 '13 at 07:24
  • You can still get the PID etc, but you'll have to use AX or AppleScript to send messages to those other apps' windows. – uchuugaka Apr 23 '13 at 07:26
  • uchuugaka - What do you mean by AX? A lot of this stuff is not well known, so I'm finding things difficult. Presently I'm trying to follow up on suggestions googled elsewhere, such as HIToolbox.framework – rootscript Apr 23 '13 at 07:42
  • AX is the prefix for the Accessibility framework. HIToolbox can do a lot if you are targeting older systems but much of it is deprecated, and not so easy to use. – uchuugaka Apr 23 '13 at 14:38