Accessibility API - moving and resizing windows (in one API call)

  • Hello All,

    I have an app that moves and resizes windows around, via the
    Accessibility API.

    I'd like to know if there is a way to make the window manager move
    *and* resize a window all in one go, rather than in two stages.  The
    reason I ask this is that while the window server is very quick etc,
    when these two operations occur very frequently (i.e. on every mouse
    movement) there is a very noticeable jarring / flickering going on
    simply because these two operations are not an atomic operation as far
    as the window server goes.

    (at least, that's my take on it).

    Here's the code I currently have in my app, that uses the
    Accessibility API to move and resize a window:

    _topLevelUIElementPosition - is the AXUIElementRef pointing to a
    window that I want to move/resize (or both)
    mouseDelta - the distance that the mouse has moved since the button
    went down

    // depending on quadrant, the resize is achieved in different ways
    switch(_resizeQuadrant)
    {
      case kZWQBottomLeft:
      {
        CGPoint absWinPos = CGPointMake(_topLevelUIElementPosition.x +
    mouseDelta.x,
                _topLevelUIElementPosition.y);

        CFTypeRef newLocRef = AXValueCreate(kAXValueCGPointType, (void
    *)&absWinPos);
        AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    kAXPositionAttribute, newLocRef) );
        CFRelease(newLocRef);

        CGSize absSizeNow = CGSizeMake(_topLevelUIElementSize.width -
    mouseDelta.x,
                                                 _topLevelUIElementSize.height + mouseDelta.y);

        CFTypeRef newSizeRef = AXValueCreate(kAXValueCGSizeType, (void
    *)&absSizeNow);
        AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    kAXSizeAttribute, newSizeRef) );
        CFRelease(newSizeRef);
      }
      break;

      case kZWQTopRight:

    The two important lines in this case are the re-positioning of an
    application window, and the resizing of it:

    AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    kAXPositionAttribute, newLocRef) );
    AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    kAXSizeAttribute, newSizeRef) );

    I'd love to somehow say something like this:
    * window server: do all the following stuff in one atomic op / begin
    transaction *

    AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    kAXPositionAttribute, newLocRef) );

    AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    kAXSizeAttribute, newSizeRef) );

      * window server: end of stuff that I want done in one transaction /
    go do it now *

    Does anyone know of a way that I could achieve this?  Thanks in
    advance, I'm happy to expound more about this as required.

    --
    John Clayton
    http://www.coderage-software.com/
  • > I'd love to somehow say something like this:
    > * window server: do all the following stuff in one atomic op /
    > begin transaction *
    >
    > AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    > kAXPositionAttribute, newLocRef) );
    >
    > AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    > kAXSizeAttribute, newSizeRef) );
    >
    > * window server: end of stuff that I want done in one
    > transaction / go do it now *

    You could try to use NSDisableScreenUpdates() and
    NSEnableScreenUpdates(). I am not sure if this works in your case,
    because it's documented to disable screen updates for all windows
    belonging to the calling process, but as far as I understand you're
    trying to control the windows of other processes. But it may be worth
    a try.

    Regards,
    Mani
    --
    http://www.mani.de
    iVolume - Loudness adjustment for iTunes.
    LittleSecrets - The encrypted notepad.
  • Hi Manfred,

    Thanks for the tip there - I tried it *immediately* :-) but no dice,
    it in fact appears to do nothing for me....... hmmmm... a nice try
    though.  My program (as you probably guessed) is manipulating other
    processes' windows via the Accessibility API, and these two methods
    appear not to have the power to influence the window server.  Shame.

    I even tried leaving of the re-enabling of the updates, leaving the
    window server to do this automatically for me after the documented 1
    second - in the hope that it was all timing related.  No dice.

    Thanks for the tip however.

    --
    John Clayton
    http://www.coderage-software.com/

    On 12/11/2007, at 2:55 PM, Manfred Schwind wrote:

    >> I'd love to somehow say something like this:
    >> * window server: do all the following stuff in one atomic op /
    >> begin transaction *
    >>
    >> AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    >> kAXPositionAttribute, newLocRef) );
    >>
    >> AXCALL_LOG( AXUIElementSetAttributeValue(_topLevelUIElement,
    >> kAXSizeAttribute, newSizeRef) );
    >>
    >> * window server: end of stuff that I want done in one
    >> transaction / go do it now *
    >
    > You could try to use NSDisableScreenUpdates() and
    > NSEnableScreenUpdates(). I am not sure if this works in your case,
    > because it's documented to disable screen updates for all windows
    > belonging to the calling process, but as far as I understand you're
    > trying to control the windows of other processes. But it may be
    > worth a try.
    >
    > Regards,
    > Mani
    > --
    > http://www.mani.de
    > iVolume - Loudness adjustment for iTunes.
    > LittleSecrets - The encrypted notepad.
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today