我们有一个具有全屏视频播放器的应用程序,可以调出一个浮动窗口(托盘),以便为用户提供修改视频的工具,只有一个视图可以播放视频,并且所有绘图都在其中进行,其NSOpenGLView子类。如果用户单击托盘上的按钮,然后将托盘移动到视频视图上,我们将使用mouseEntered:将光标-[NSCursor set]更新为一个以反映用户正在绘制,但是大约一秒钟之后,可可将光标重新设置为箭头光标。
我在-[NSCursor set]上创建了一个符号断点,以查看它来自哪里,这就是我得到的调用堆栈。
0 ??? 0x000000010cade785 0x0 + 4507690885,
1 Periscope HiDef4 0x00000001001d3f70 main + 0,
2 AppKit 0x00007fff4da7c55e __37+[NSDisplayCycle currentDisplayCycle]_block_invoke + 695,
3 QuartzCore 0x00007fff5b73b8c7 _ZN2CA11Transaction19run_commit_handlersE18CATransactionPhase + 49,
4 QuartzCore 0x00007fff5b73a389 _ZN2CA11Transaction6commitEv + 171,
5 AppKit 0x00007fff4e234a72 __65+[CATransaction(NSCATransaction) NS_setFlushesWithDisplayRefresh]_block_invoke + 283,
6 CoreFoundation 0x00007fff503ca737 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23,
7 CoreFoundation 0x00007fff503ca65f __CFRunLoopDoObservers + 511,
8 CoreFoundation 0x00007fff503ad128 __CFRunLoopRun + 1240,
9 CoreFoundation 0x00007fff503ac9b7 CFRunLoopRunSpecific + 487,
10 HIToolbox 0x00007fff4f68cd96 RunCurrentEventLoopInMode + 286,
11 HIToolbox 0x00007fff4f68cb06 ReceiveNextEventCommon + 613,
12 HIToolbox 0x00007fff4f68c884 _BlockUntilNextEventMatchingListInModeWithFilter + 64,
13 AppKit 0x00007fff4d93da73 _DPSNextEvent + 2085,
14 AppKit 0x00007fff4e0d3e34 -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] + 3044,
15 AppKit 0x00007fff4d932885 -[NSApplication run] + 764,
16 AppKit 0x00007fff4d901a72 NSApplicationMain + 804,
17 Periscope HiDef4 0x00000001001d3f92 main + 34,
18 libdyld.dylib 0x00007fff7828a015 start + 1,
19 ??? 0x0000000000000003 0x0 + 3
我尝试将实现从使用-[NSCursor set]和mouseEntered:事件更改为-[NSView addCursorRect:cursor:],并使用整个视图范围的矩形,但这根本不会设置光标,可能是因为我们正在使用NSOpenGLView子类吗?
奇怪的是,光标并非总是会重置,如果您单击按钮并暂停然后将其移离托盘,我们不会获得带有上述堆栈的-[NSCursor set],只有当您直接移动时,这可能与更改托盘的调整窗口框架光标大小有关,但我不确定。
我想出了一个使用mouseMoved的解决方案:检查光标是否应该是它的样子,但是只有在用户移动光标时它才起作用,我宁愿弄清楚为什么我得到了不需要的-[NSCursor设置],然后改正它。