Custom-view cursor changing

  • I have a custom NSView subclass which overrides -mouseDown:,
    -mouseDragged: and -mouseUp:. In response to dragging, the control can
    resize itself and some ancillary views in the window (within a limited
    range, of course). Conceptually it's a lot like a split view.

    I am trying to change the cursor when the drag starts by calling
    [myCursor push] inside -mouseDown:, and restoring it via [NSCursor pop]
    inside -mouseUp:. I'm finding that if I just click and release, this
    works great.

    However, dragging does not work as expected. When -mouseDragged: is
    called and I change various views' bounds (via setFrame), suddenly the
    cursor pops back to being an arrow cursor.

    This appears to be happening because some view I'm using is posting a
    notification saying that it needs to reset its cursor rects. When I set
    a breakpoint on -[NSCursor set], I get this:

    #0    0x911034d6 in -[NSCursor set]
    #1    0x913dbafd in -[NSWindow resetCursorRects]
    #2    0x91108315 in _handleInvalidCursorRectsNote
    #3    0x90f039e2 in __CFRunLoopDoObservers
    #4    0x90f04d45 in CFRunLoopRunSpecific
    #5    0x90f05d38 in CFRunLoopRunInMode
    #6    0x92cf28a4 in RunCurrentEventLoopInMode
    #7    0x92cf25f6 in ReceiveNextEventCommon
    #8    0x92cf2531 in BlockUntilNextEventMatchingListInMode
    #9    0x9107cd5b in _DPSNextEvent
    #10    0x9107c6a0 in -[NSApplication
    nextEventMatchingMask:untilDate:inMode:dequeue:]
    #11    0x910756d1 in -[NSApplication run]

    I don't know exactly how to solve this, though. I'm definitely not
    posting anything like this, and the other views involved are all
    standard OS X NSViews (e.g. in this case there are NSOutlineViews,
    NSButtons and NSTextViews… not exactly rocket science).

    Has anyone seen this before and maybe found a workaround? Maybe I need
    to do something to enable "live-resize mode" in my mouseDown/mouseUp
    methods?

    I notice that I'm not alone—Xcode has the same problem when dragging its
    splitter in the main project window.
  • Heh, of course, after posting I found a workaround. In -mouseDown: you
    can do:
        [[self window] disableCursorRects];

    And in -mouseUp:
        [[self window] enableCursorRects];
        [[self window] resetCursorRects];

    And this resolves the issue.

    There are two things I'm still not sure of:
    - Is -resetCursorRects necessary here? Or is the re-enable enough to
    take care of everything?
    - Is this actually a good solution? It seems to work fine but I am not
    really sure if it's the best approach.

    John Stiles wrote:
    > I have a custom NSView subclass which overrides -mouseDown:,
    > -mouseDragged: and -mouseUp:. In response to dragging, the control can
    > resize itself and some ancillary views in the window (within a limited
    > range, of course). Conceptually it's a lot like a split view.
    >
    > I am trying to change the cursor when the drag starts by calling
    > [myCursor push] inside -mouseDown:, and restoring it via [NSCursor
    > pop] inside -mouseUp:. I'm finding that if I just click and release,
    > this works great.
    >
    > However, dragging does not work as expected. When -mouseDragged: is
    > called and I change various views' bounds (via setFrame), suddenly the
    > cursor pops back to being an arrow cursor.
    >
    > This appears to be happening because some view I'm using is posting a
    > notification saying that it needs to reset its cursor rects. When I
    > set a breakpoint on -[NSCursor set], I get this:
    >
    > #0    0x911034d6 in -[NSCursor set]
    > #1    0x913dbafd in -[NSWindow resetCursorRects]
    > #2    0x91108315 in _handleInvalidCursorRectsNote
    > #3    0x90f039e2 in __CFRunLoopDoObservers
    > #4    0x90f04d45 in CFRunLoopRunSpecific
    > #5    0x90f05d38 in CFRunLoopRunInMode
    > #6    0x92cf28a4 in RunCurrentEventLoopInMode
    > #7    0x92cf25f6 in ReceiveNextEventCommon
    > #8    0x92cf2531 in BlockUntilNextEventMatchingListInMode
    > #9    0x9107cd5b in _DPSNextEvent
    > #10    0x9107c6a0 in -[NSApplication
    > nextEventMatchingMask:untilDate:inMode:dequeue:]
    > #11    0x910756d1 in -[NSApplication run]
    >
    > I don't know exactly how to solve this, though. I'm definitely not
    > posting anything like this, and the other views involved are all
    > standard OS X NSViews (e.g. in this case there are NSOutlineViews,
    > NSButtons and NSTextViews… not exactly rocket science).
    >
    > Has anyone seen this before and maybe found a workaround? Maybe I need
    > to do something to enable "live-resize mode" in my mouseDown/mouseUp
    > methods?
    >
    > I notice that I'm not alone—Xcode has the same problem when dragging
    > its splitter in the main project window.
  • Am 27.11.2007 um 22:46 schrieb John Stiles:
    > This appears to be happening because some view I'm using is posting
    > a notification saying that it needs to reset its cursor rects. When
    > I set a breakpoint on -[NSCursor set], I get this:

      I think it'd be best if you just made your view change its cursor
    rects while it is tracking. I'd expect your view to be called to reset
    its cursor rects, too. Can't you just set a flag there and update your
    own cursor rects as needed?

    Cheers,
    -- M. Uli Kusterer
    "The Witnesses of TeachText are everywhere..."
    http://www.zathras.de
  • Uli Kusterer wrote:
    > Am 27.11.2007 um 22:46 schrieb John Stiles:
    >> This appears to be happening because some view I'm using is posting a
    >> notification saying that it needs to reset its cursor rects. When I
    >> set a breakpoint on -[NSCursor set], I get this:
    >
    >
    > I think it'd be best if you just made your view change its cursor
    > rects while it is tracking. I'd expect your view to be called to reset
    > its cursor rects, too. Can't you just set a flag there and update your
    > own cursor rects as needed?
    It's not my view that is the problem—my view is a simple subclass of
    NSView that only overrides drawRect:, mouseDown:, mouseUp: and
    mouseDragged:. In other words, no cursor rects at all.
    It's some other standard OS view that is causing the trouble. I'm not
    even sure which one because it's not really evident from the stack crawl.
    To be clear, I've tried changing my code so that in mouseDragged:, I
    only set my own view's frame and not any other view's frames. In this
    case everything works fine. It's only when I start calling setFrame: on
    other views that there is a problem.
  • On 28 Nov 2007, at 12:03, Uli Kusterer wrote:

    > I think it'd be best if you just made your view change its cursor
    > rects while it is tracking. I'd expect your view to be called to
    > reset its cursor rects, too. Can't you just set a flag there and
    > update your own cursor rects as needed?

    FWIW, I think the approach John has taken (i.e. using -enable/-
    disableCursorRects) is a perfectly sensible one.  If you're tracking
    the mouse using the three-method approach, you actually don't want
    other peoples' cursor rects causing your pointer to change in most
    cases (consider, for instance, the case where the user is dragging a
    slider, and as they do so they stray over e.g. a text field or a link
    in a WebView or something).

    Kind regards,

    Alastair.

    --
    http://alastairs-place.net
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