Re: AXPosition and AXSize during window drags
Re: AXPosition and AXSize during window drags
- Subject: Re: AXPosition and AXSize during window drags
- From: Bill Cheeseman <email@hidden>
- Date: Mon, 26 Nov 2007 12:13:50 -0500
- Thread-topic: AXPosition and AXSize during window drags
on 2007-11-25 1:14 PM, Bill Cheeseman at email@hidden wrote:
> on 2007-11-25 12:24 PM, Michael Ash at email@hidden wrote:
>
>> On Nov 25, 2007, at 12:18 PM, Bill Cheeseman wrote:
>>
>>> As I outlined in another message, Quartz Event Taps gives me an
>>> opportunity
>>> to do something repeatedly during a drag of any application's
>>> window, Cocoa
>>> or otherwise. The question is, what can I look at during each of those
>>> repetitive opportunities?
>>
>> Your mention of Leopard-only brings to mind the CGWindow APIs, which
>> allow you to get the bounds of any window on screen. I would hope that
>> since this API seems to talk directly to the window server, it will
>> get you the real location of any window no matter what the
>> circumstances. You may experience tearing due to synchronization
>> issues but it's certainly better than the alternative.
>
> Thanks for the tip. I had started looking at that yesterday but got
> sidetracked. It does look promising. I'll give it a shot.
It works! My overlay window now moves and resizes in nearly perfect
synchronization with the underlying window, Cocoa or not. I say "nearly"
because, if I wildly snap the mouse back and forth, I can see the slightest
lag on one window edge, on a 2.5G dual G5 machine. In more normal use, the
appearance is perfect.
Here's my code. You'll have to treat this as pseudocode in part, because
there are a number of calls to my private PFAssistive and PFEventTaps
frameworks. The nomenclature should make them self explanatory. Note again
that this requires Leopard.
When turning on my overlay window (a borderless semitransparent highlighting
window), I locate the target window in the global window list by matching
the pid of the application that owns the target window and the window
bounds. Then I save its CGWindowID for later use.
- (CGWindowID)getHighlightedWindowNumber {
CGWindowID windowNumber = kCGNullWindowID;
NSArray *windowList = (NSArray
*)CGWindowListCopyWindowInfo(kCGWindowListOptionAll |
kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements,
kCGNullWindowID);
if (windowList) {
PFUIElement *element = ([[self highlightedElement]
isRole:NSAccessibilityWindowRole]) ? [self highlightedElement] : [[self
highlightedElement] AXWindow];
NSRect elementWindowBounds = {[[element AXPosition] pointValue],
[[element AXSize] sizeValue]};
int elementPID = [element pid];
NSDictionary *highlightedWindowDictionary = nil;
for (NSDictionary *thisWindowDictionary in windowList) {
// Get the window of the target application containing a
highlighted UI element by matching the window dictionary's pid to the
element's pid and the window dictionary's bounds to the element's window's
bounds.
int targetPID = [[thisWindowDictionary objectForKey:(NSString
*)kCGWindowOwnerPID] intValue];
if (targetPID == elementPID) {
CGRect bounds;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[thisWindowDictionar
y objectForKey:(NSString *)kCGWindowBounds], &bounds);
NSRect targetWindowBounds = NSRectFromCGRect(bounds);
if (NSEqualRects(targetWindowBounds, elementWindowBounds)) {
highlightedWindowDictionary = thisWindowDictionary;
break;
}
}
}
windowNumber = [[highlightedWindowDictionary objectForKey:(NSString
*)kCGWindowNumber] unsignedLongValue];
CFRelease(windowList);
}
return windowNumber;
}
When my event tap's delegate method fires repeatedly while the target window
is being dragged or resized, I reset the frame of the overlay window by
getting the new bounds of the target window, using the saved CGWindowID.
- (void)eventTap:(PFEventTap *)tap didPostEvent:(PFEvent *)event {
// Delegate method per PFEventTap to monitor left mouse dragged, mouse
down and mouse up events, in order to move and resize the highlighting
overlay window synchronously with the underlying highlighted UI element.
NSRect highlightRect = NSZeroRect;
NSArray *windowNumbers = [NSArray arrayWithObject:(void *)[self
highlightedWindowNumber]]; // windowNumber is pointer
NSArray *windowList = (NSArray
*)CGWindowListCreateDescriptionFromArray((CFArrayRef)windowNumbers);
if ([windowList count] == 1) {
NSDictionary *thisWindow = [windowList objectAtIndex:0];
CGRect bounds;
CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)[thisWindow
objectForKey:(NSString *)kCGWindowBounds], &bounds);
highlightRect = NSRectFromCGRect(bounds);
if (!NSEqualRects(highlightRect, NSZeroRect)) {
highlightRect.origin.y = NSMaxY([[[NSScreen screens]
objectAtIndex:0] frame]) - NSMaxY(highlightRect); // flip
if ([[NSUserDefaults standardUserDefaults]
boolForKey:HIGHLIGHT_ANIMATES_DEFAULTS_KEY]) {
[[[self overlayWindow] animator] setFrame:highlightRect
display:YES];
} else {
[[self overlayWindow] setFrame:highlightRect display:YES];
}
}
CFRelease(windowList);
}
}
Sorry about the messy line breaks.
--
Bill Cheeseman - email@hidden
Quechee Software, Quechee, Vermont, USA
www.quecheesoftware.com
PreFab Software - www.prefabsoftware.com
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Accessibility-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden