[Qt-interest] QTreeView Wierdness with OS X Cocoa Qt 4.5.0

Dennis Wilkinson Dennis.Wilkinson at mathworks.com
Sun Apr 26 17:58:16 CEST 2009


> On 2009-03-28 11:20:47 -0400, Mike Jackson <imikejackson at
> gmail.com> said:
>
> > On 2009-03-28 11:05:45 -0400, Mike Jackson <imikejackson at
> gmail.com> said:
> >
> >> I have an application that uses a QTreeView with a custom TreeModel
> >> implementation. When I build against Qt 4.5 (Cocoa 32 Bit) the
> top few
> >> items do not seem to receive any mouse clicks. I can use the
> keyboard
> >> arrow key to highlight the top (root) item then use the arrow key
> again
> >> to reveal but it takes a few of these iterations to finally be
> able to
> >> let the mouse have any effect on the tree view (like showing and
> >> hiding) nodes.
> >>
> >>   Has anyone else seen anything like this? When I recompile
> against a
> >> 32 bit Qt 4.4.3 build (Carbon) the tree acts just fine.
> >>
> >> I have not compiled against a carbon Qt 4.5 though to see if it
> is the
> >> Cocoa/Carbon thing or the 4.4 to 4.5 thing.
> >>
> >> Any help would be appreciated.
> >>
> >> Mike Jackson
> >
> > I also noticed the same issues with Qt Designer and the tool
> pallettes,
> > specifically the Object Inspector. The same issues happen there
> also. I
> > can not use the mouse to make a selection (single or double
> click). Not
> > sure if this is all related but might seem to be.
> >
> >  Also, this is with a new Mac Pro if that matters at all.
> >
> > Thanks
> > Mike Jackson
>
> Anyone else had this problem? Did I miss something in my build? Should
> I file a formal bug report?
>

I've just finished debugging the same symptoms. Are you by any chance
hiding the header() for the QTreeView?

It looks to me like the logic in [QCocoaView
viewUnderTransparentForMouseView:widget:withWindowPoint:] in src/gui/
kernel/qcocoaview_mac.mm is failing to account for NSViews that are
hidden, like the NSView underlying the QTreeView's QHeaderView in this
case. I'm working around it by installing an event filter on the
QHeaderView and redispatching all mouse events to the viewport() if
the header is hidden, but I think that changing the QCocoaView
implementation to what I've posted below is a reasonable patch
(hopefully it doesn't get rewrapped too badly).

This looks to still be an issue in 4.5.1/Cocoa.

- (NSView *)viewUnderTransparentForMouseView:(NSView *)mouseView
widget:(QWidget *)widgetToGetMouse
                              withWindowPoint:(NSPoint)windowPoint
{
     NSMutableArray *viewsToLookAt = [NSMutableArray arrayWithCapacity:
5];
     [viewsToLookAt addObject:mouseView];
     QWidget *parentWidget = widgetToGetMouse->parentWidget();
     while (parentWidget) {
         [viewsToLookAt addObject:qt_mac_nativeview_for(parentWidget)];
         parentWidget = parentWidget->parentWidget();
     }

     // Now walk through the subviews of each view and determine which
subview should
     // get the event. We look through all the subviews at a given
level with
     // the assumption that the last item to be found the candidate
has a higher z-order.
     // Unfortunately, fast enumeration doesn't go backwards in 10.5,
so assume go fast
     // forward is quicker than the slow normal way backwards.
     NSView *candidateView = nil;
     for (NSView *lookView in viewsToLookAt) {
         NSPoint tmpPoint = [lookView convertPoint:windowPoint
fromView:nil];
         for (NSView *view in [lookView subviews]) {
             if (view == mouseView || [view isHidden]) // don't hit
test hidden views!
                 continue;
             NSRect frameRect = [view frame];
             if (NSMouseInRect(tmpPoint, [view frame], [view
isFlipped]))
                 candidateView = view;
         }
         if (candidateView)
             break;
     }


     if (candidateView != nil) {
         // Now that we've got a candidate, we have to dig into it's
tree and see where it is.
         NSView *lowerView = nil;
         NSView *viewForDescent = candidateView;
         while (viewForDescent) {
             NSPoint tmpPoint = [viewForDescent
convertPoint:windowPoint fromView:nil];
             // Apply same rule as above wrt z-order.
             for (NSView *view in [viewForDescent subviews]) {
                 if ([view isHidden]) // don't hit test hidden views!
                     continue;
                 if (NSMouseInRect(tmpPoint, [view frame], [view
isFlipped]))
                     lowerView = view;
             }
             if (!lowerView) // Low as we can be at this point.
                 candidateView = viewForDescent;

             // Try to go deeper, will also exit out of the loop, if
we found the point.
             viewForDescent = lowerView;
             lowerView = nil;
         }
     }
     // I am transparent, so I can't be a candidate.
     if (candidateView == mouseView)
         candidateView = nil;
     return candidateView;
}

--
Dennis

Dennis J. Wilkinson, II
Graphical Languages UI Engineer
The MathWorks, Inc.
dennis.wilkinson(at)mathworks.com






More information about the Qt-interest-old mailing list