Skip to content

Commit

Permalink
Updated the WindowSizer related API.
Browse files Browse the repository at this point in the history
  • Loading branch information
Filip Krikava committed Nov 8, 2010
1 parent e29ee1c commit 6e039d0
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 114 deletions.
6 changes: 4 additions & 2 deletions ShiftIt/AXUIUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,10 @@
*/

int AXUISetWindowGeometry(void *window, int x, int y, unsigned int width, unsigned int height);
int AXUIGetActiveWindowGeometry(void **activeWindow, int *x, int *y, unsigned int *width, unsigned int *height);
int AXUISetWindowPosition(void *window, int x, int y);
int AXUISetWindowSize(void *window, unsigned int width, unsigned int height);
int AXUIGetActiveWindow(void **activeWindow);
int AXUIGetWindowGeometry(void *window, int *x, int *y, unsigned int *width, unsigned int *height);
void AXUIFreeWindowRef(void *window);

const char *AXUIGetErrorMessage(int code);
69 changes: 38 additions & 31 deletions ShiftIt/AXUIUtils.m
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,9 @@

static int kErrorMessageCount_ = sizeof(kErrorMessages_)/sizeof(kErrorMessages_[0]);

// TODO: assert
int AXUISetWindowGeometry(void *window, int x, int y, unsigned int width, unsigned int height) {
int AXUISetWindowPosition(void *window, int x, int y) {
FMTAssertNotNil(window);

NSPoint position = {x, y};
CFTypeRef positionRef = (CFTypeRef)(AXValueCreate(kAXValueCGPointType, (const void *)&position));
if(AXUIElementSetAttributeValue((AXUIElementRef)window,(CFStringRef)NSAccessibilityPositionAttribute,(CFTypeRef*)positionRef) != kAXErrorSuccess){
Expand All @@ -47,6 +46,12 @@ int AXUISetWindowGeometry(void *window, int x, int y, unsigned int width, unsign
}
CFRelease(positionRef);

return 0;
}

int AXUISetWindowSize(void *window, unsigned int width, unsigned int height) {
FMTAssertNotNil(window);

NSSize size = {width, height};
CFTypeRef sizeRef = (CFTypeRef)(AXValueCreate(kAXValueCGSizeType, (const void *)&size));
if(AXUIElementSetAttributeValue((AXUIElementRef)window,(CFStringRef)NSAccessibilitySizeAttribute,(CFTypeRef*)sizeRef) != kAXErrorSuccess){
Expand All @@ -58,29 +63,12 @@ int AXUISetWindowGeometry(void *window, int x, int y, unsigned int width, unsign
return 0;
}

void AXUIFreeWindowRef(void *window) {
FMTAssertNotNil(window);

CFRelease((CFTypeRef) window);
}

const char *AXUIGetErrorMessage(int code) {
FMTAssert(code < 0 && code > -kErrorMessageCount_, @"error code must be %d < code < 0", -kErrorMessageCount_);

return kErrorMessages_[-code-1];
}

int AXUIGetActiveWindowGeometry(void **activeWindow, int *x, int *y, unsigned int *width, unsigned int *height) {
FMTAssertNotNil(x);
FMTAssertNotNil(y);
FMTAssertNotNil(width);
FMTAssertNotNil(height);

int AXUIGetActiveWindow(void **activeWindow) {
AXUIElementRef systemElementRef = AXUIElementCreateSystemWide();
// here is the assert for purpose because the app should not have gone
// that far in execution if the AX api is not available
FMTAssertNotNil(systemElementRef);

//get the focused application
AXUIElementRef focusedAppRef = nil;
AXError axerror = AXUIElementCopyAttributeValue(systemElementRef,
Expand All @@ -104,23 +92,31 @@ int AXUIGetActiveWindowGeometry(void **activeWindow, int *x, int *y, unsigned in
}
FMTAssertNotNil(focusedWindowRef);
*activeWindow = (void *) focusedWindowRef;

return 0;
}

int AXUIGetWindowGeometry(void *window, int *x, int *y, unsigned int *width, unsigned int *height) {
FMTAssertNotNil(x);
FMTAssertNotNil(y);
FMTAssertNotNil(width);
FMTAssertNotNil(height);

//get the position
CFTypeRef positionRef;
NSPoint position;
axerror = AXUIElementCopyAttributeValue((AXUIElementRef)focusedWindowRef,(CFStringRef)NSAccessibilityPositionAttribute,(CFTypeRef*)&positionRef);

int axerror = AXUIElementCopyAttributeValue((AXUIElementRef)window,(CFStringRef)NSAccessibilityPositionAttribute,(CFTypeRef*)&positionRef);
if (axerror != kAXErrorSuccess) {
CFRelease(focusedWindowRef);

return -3;
}

FMTAssertNotNil(positionRef);
if(AXValueGetType(positionRef) == kAXValueCGPointType) {
AXValueGetValue(positionRef, kAXValueCGPointType, (void*)&position);
*x = (int) position.x;
*y = (int) position.y;
} else {
CFRelease(focusedWindowRef);
CFRelease(positionRef);

return -4;
Expand All @@ -130,24 +126,35 @@ int AXUIGetActiveWindowGeometry(void **activeWindow, int *x, int *y, unsigned in
//get the focused size
CFTypeRef sizeRef;
NSSize size;
axerror = AXUIElementCopyAttributeValue((AXUIElementRef)focusedWindowRef,(CFStringRef)NSAccessibilitySizeAttribute,(CFTypeRef*)&sizeRef);

axerror = AXUIElementCopyAttributeValue((AXUIElementRef)window,(CFStringRef)NSAccessibilitySizeAttribute,(CFTypeRef*)&sizeRef);
if (axerror != kAXErrorSuccess) {
CFRelease(focusedWindowRef);

return -5;
}

FMTAssertNotNil(sizeRef);
if(AXValueGetType(sizeRef) == kAXValueCGSizeType) {
AXValueGetValue(sizeRef, kAXValueCGSizeType, (void*)&size);
*width = (unsigned int) size.width;
*height = (unsigned int) size.height;
} else {
CFRelease(focusedWindowRef);
CFRelease(sizeRef);

return -6;
}
CFRelease(sizeRef);

return 0;
}

void AXUIFreeWindowRef(void *window) {
FMTAssertNotNil(window);

CFRelease((CFTypeRef) window);
}

const char *AXUIGetErrorMessage(int code) {
FMTAssert(code < 0 && code > -kErrorMessageCount_, @"error code must be %d < code < 0", -kErrorMessageCount_);

return kErrorMessages_[-code-1];
}
4 changes: 3 additions & 1 deletion ShiftIt/ShiftIt.h
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ extern NSString *const kSIMenuItemTitle;

extern NSString *const SIErrorDomain;
extern NSInteger const kUnableToGetActiveWindowErrorCode;
extern NSInteger const kUnableToChangeWindowSizeOrPositionErrorCode;
extern NSInteger const kUnableToChangeWindowPositionErrorCode;
extern NSInteger const kUnableToGetWindowGeometryErrorCode;
extern NSInteger const kUnableToChangeWindowSizeErrorCode;

#define KeyCodePrefKey(identifier) FMTStr(@"%@%@", (identifier), kKeyCodePrefKeySuffix)
#define ModifiersPrefKey(identifier) FMTStr(@"%@%@", (identifier), kModifiersPrefKeySuffix)
Expand Down
4 changes: 3 additions & 1 deletion ShiftIt/ShiftItAppDelegate.m
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@
// error related
NSString *const SIErrorDomain = @"org.shiftitapp.shiftit.ErrorDomain";
NSInteger const kUnableToGetActiveWindowErrorCode = 20100;
NSInteger const kUnableToChangeWindowSizeOrPositionErrorCode = 20101;
NSInteger const kUnableToChangeWindowPositionErrorCode = 20101;
NSInteger const kUnableToGetWindowGeometryErrorCode = 20102;
NSInteger const kUnableToChangeWindowSizeErrorCode = 20102;

NSDictionary *allShiftActions = nil;

Expand Down
108 changes: 71 additions & 37 deletions ShiftIt/WindowSizer.m
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

#define RECT_STR(rect) FMTStr(@"[%f %f] [%f %f]", (rect).origin.x, (rect).origin.y, (rect).size.width, (rect).size.height)

extern int abs(int i);

// reference to the carbon GetMBarHeight() function
extern short GetMBarHeight(void);

Expand Down Expand Up @@ -99,55 +101,71 @@ - (void) shiftFocusedWindowUsing:(ShiftItAction *)action error:(NSError **)error
FMTAssertNotNil(action);

#ifdef X11
// following will make the X11 reference coordinate system
// X11 coordinates starts at the very top left corner of the most top left window
// basically it is a union of all screens with the beginning at the top left
NSRect X11Ref = [[NSScreen primaryScreen] frame];
for (NSScreen *screen in [NSScreen screens]) {
X11Ref = NSUnionRect(X11Ref, [screen frame]);
}
// translate
COCOA_TO_SCREEN_COORDINATES(X11Ref);
FMTDevLog(@"X11 reference rect: %@", RECT_STR(X11Ref));

bool activeWindowX11 = NO;
bool activeWindowX11 = NO;
NSRect X11Ref;
#endif // X11

// window reference - windowing system agnostic
void *window = NULL;

// coordinates vars
int x,y;
unsigned int width, height;
int x = 0, y = 0;
unsigned int width = 0, height = 0;

// error handling vars
int errorCode = 0;

// active window geometry

// first try to get the window using accessibility API
errorCode = AXUIGetActiveWindowGeometry(&window, &x, &y, &width, &height);
errorCode = AXUIGetActiveWindow(&window);

if (errorCode != 0) {
#ifdef X11
window = NULL;
// try X11
int errorCodeX11 = X11GetActiveWindowGeometry(&window, &x, &y, &width, &height);
int errorCodeX11 = X11GetActiveWindow(&window);
if (errorCodeX11 != 0) {
NSString *message = FMTStr(@"%@, %@",FMTStrc(AXUIGetErrorMessage(errorCode)),FMTStrc(X11GetErrorMessage(errorCodeX11)));

*error = SICreateError(message, kUnableToGetActiveWindowErrorCode);
return;
} else {
FMTDevLog(@"window rect (x11): [%d %d] [%d %d]", x, y, width, height);

// convert from X11 coordinates to Quartz CG coodinates
x += X11Ref.origin.x;
y += X11Ref.origin.y;

activeWindowX11 = YES;
}

int errorCode = X11GetWindowGeometry(window, &x, &y, &width, &height);
if (errorCode != 0) {
*error = SICreateError(FMTStrc(X11GetErrorMessage(errorCode)), kUnableToGetWindowGeometryErrorCode);
return;
}
FMTDevLog(@"window rect (x11): [%d %d] [%d %d]", x, y, width, height);

// following will make the X11 reference coordinate system
// X11 coordinates starts at the very top left corner of the most top left window
// basically it is a union of all screens with the beginning at the top left
X11Ref = [[NSScreen primaryScreen] frame];
for (NSScreen *screen in [NSScreen screens]) {
X11Ref = NSUnionRect(X11Ref, [screen frame]);
}
// translate
COCOA_TO_SCREEN_COORDINATES(X11Ref);
FMTDevLog(@"X11 reference rect: %@", RECT_STR(X11Ref));

// convert from X11 coordinates to Quartz CG coodinates
x += X11Ref.origin.x;
y += X11Ref.origin.y;

activeWindowX11 = YES;
#else
*error = SICreateError(FMTStrc(AXUIGetErrorMessage(errorCode)), kUnableToGetActiveWindowErrorCode);
return;
#endif // X11
} else {
int errorCode = AXUIGetWindowGeometry(window, &x, &y, &width, &height);

if (errorCode != 0) {
*error = SICreateError(FMTStrc(AXUIGetErrorMessage(errorCode)), kUnableToGetWindowGeometryErrorCode);
return;
}
}

// the window rect in screen coordinates
Expand Down Expand Up @@ -213,7 +231,6 @@ - (void) shiftFocusedWindowUsing:(ShiftItAction *)action error:(NSError **)error
if (screenBelowPrimary || [screen isPrimary]) {
shiftedRect.origin.y -= GetMBarHeight();
}

}
#endif // X11

Expand All @@ -225,25 +242,42 @@ - (void) shiftFocusedWindowUsing:(ShiftItAction *)action error:(NSError **)error
height = (unsigned int) shiftedRect.size.height;

// adjust window geometry
// there are apps that does not size continuously but rather discretely so
// they have to be re-adjusted hence first set the size and then position
#ifdef X11
if (activeWindowX11) {
errorCode = X11SetWindowGeometry(window, x, y, width, height);
if (activeWindowX11) {
FMTDevLog(@"adjusting position to %dx%d", x, y);
errorCode = X11SetWindowPosition(window, x, y);
if (errorCode != 0) {
*error = SICreateError(FMTStrc(X11GetErrorMessage(errorCode)), kUnableToChangeWindowSizeOrPositionErrorCode);
*error = SICreateError(FMTStrc(X11GetErrorMessage(errorCode)), kUnableToChangeWindowPositionErrorCode);
return;
}

FMTDevLog(@"adjusting size to %dx%d", width, height);
errorCode = X11SetWindowSize(window, width, height);
if (errorCode != 0) {
*error = SICreateError(FMTStrc(X11GetErrorMessage(errorCode)), kUnableToChangeWindowSizeErrorCode);
return;
}
} else {
errorCode = AXUISetWindowGeometry(window, x, y, width, height);
#endif // X11
FMTDevLog(@"adjusting position to %dx%d", x, y);
errorCode = AXUISetWindowPosition(window, x, y);
if (errorCode != 0) {
*error = SICreateError(FMTStrc(AXUIGetErrorMessage(errorCode)), kUnableToChangeWindowSizeOrPositionErrorCode);
*error = SICreateError(FMTStrc(AXUIGetErrorMessage(errorCode)), kUnableToChangeWindowPositionErrorCode);
return;
}

FMTDevLog(@"adjusting size to %dx%d", width, height);
errorCode = AXUISetWindowSize(window, width, height);
if (errorCode != 0) {
*error = SICreateError(FMTStrc(AXUIGetErrorMessage(errorCode)), kUnableToChangeWindowSizeErrorCode);
return;
}
#ifdef X11
}
#else
errorCode = AXUISetWindowGeometry(window, x, y, width, height);
if (errorCode != 0) {
*error = SICreateError(FMTStrc(AXUIGetErrorMessage(errorCode)), kUnableToChangeWindowSizeOrPositionErrorCode);
}
#endif

#endif // X11

#ifdef X11
if (activeWindowX11) {
X11FreeWindowRef(window);
Expand Down
Loading

0 comments on commit 6e039d0

Please sign in to comment.