uilib.py (47392B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\carbonui\uilib.py 2 import math 3 import weakref 4 import blue 5 import log 6 import telemetry 7 import carbonui.const as uiconst 8 import carbonui.control 9 import evegraphics.settings as gfxsettings 10 import trinity 11 import uthread 12 from carbon.common.script.sys.serviceConst import ROLE_GML 13 from carbon.common.script.util.timerstuff import AutoTimer 14 from carbonui.text.settings import font_shadow_enabled_setting 15 from carbonui.util.weakrefutil import CallableWeakRef 16 from eve.client.script.ui.services.uiColorSettings import show_window_bg_blur_setting 17 from eveexceptions import UserError 18 from logmodule import LogException 19 from carbonui.mousesettings import CursorSize, cursor_size_setting 20 DBLCLICKDELAY = 250.0 21 CLICKCOUNTRESETTIME = 250 22 HOVERTIME = 250 23 24 def IsMacOS(): 25 import sys 26 return sys.platform.startswith('darwin') 27 28 29 class Uilib(object): 30 __notifyevents__ = ['OnUIScalingChange', 31 'OnSessionChanged', 32 'OnGraphicSettingsChanged', 33 'OnUIColorsChanged', 34 'OnFontSizeChanged'] 35 UTHREADEDEVENTS = (uiconst.UI_CLICK, 36 uiconst.UI_DBLCLICK, 37 uiconst.UI_TRIPLECLICK, 38 uiconst.UI_KEYUP, 39 uiconst.UI_KEYDOWN, 40 uiconst.UI_MOUSEMOVE) 41 EVENTMAP = {uiconst.UI_MOUSEHOVER: 'OnMouseHover', 42 uiconst.UI_MOUSEMOVE: 'OnMouseMove', 43 uiconst.UI_MOUSEMOVEDRAG: 'OnMouseMoveDrag', 44 uiconst.UI_MOUSEENTER: 'OnMouseEnter', 45 uiconst.UI_MOUSEEXIT: 'OnMouseExit', 46 uiconst.UI_MOUSEDOWN: 'OnMouseDown', 47 uiconst.UI_MOUSEDOWNDRAG: 'OnMouseDownDrag', 48 uiconst.UI_MOUSEUP: 'OnMouseUp', 49 uiconst.UI_MOUSEWHEEL: 'OnMouseWheel', 50 uiconst.UI_CLICK: 'OnClick', 51 uiconst.UI_DBLCLICK: 'OnDblClick', 52 uiconst.UI_TRIPLECLICK: 'OnTripleClick', 53 uiconst.UI_KEYDOWN: 'OnKeyDown', 54 uiconst.UI_KEYUP: 'OnKeyUp', 55 uiconst.UI_CHAR: 'OnChar'} 56 tooltipHandler = None 57 auxiliaryTooltip = None 58 auxiliaryTooltipPosition = None 59 cursorPos = (-1, -1) 60 61 def __init__(self, paparazziMode = False): 62 if not paparazziMode: 63 sm.RegisterNotify(self) 64 if len(trinity.textureAtlasMan.atlases) == 0: 65 trinity.textureAtlasMan.AddAtlas(trinity.PIXEL_FORMAT.B8G8R8A8_UNORM, 2048, 2048) 66 self.textureAtlas = trinity.textureAtlasMan.atlases[0] 67 self.textureAtlas.optimizeOnRemoval = False 68 self.renderObjectToPyObjectDict = weakref.WeakValueDictionary() 69 self.x = -1 70 self.y = -1 71 self.z = 0 72 self.dx = 0 73 self.dy = 0 74 self.dz = 0 75 self._mouseOver = None 76 self._auxMouseOverRO = None 77 self._capturingMouseItem = None 78 self._clickItem = None 79 self._mouseTargetObject = None 80 self.exclusiveMouseFocusActive = False 81 self.appfocusitem = None 82 self.selectedCursorType = uiconst.UICURSOR_DEFAULT 83 self.centerMouse = False 84 self.ignoreDeadChar = None 85 self._clickTime = None 86 self._clickCount = 0 87 self._clickTimer = None 88 self._clickPosition = None 89 self.rootObjects = [] 90 self.rootObjectsByName = {} 91 self._triuiRegs = {} 92 self._triuiRegsByMsgID = {} 93 self._mouseButtonStates = {} 94 self._mouseDownPosition = {} 95 self._appfocusitem = None 96 self._modkeysOff = tuple([ 0 for x in uiconst.MODKEYS ]) 97 self._expandMenu = None 98 self._keyDownAcceleratorThread = None 99 self.blurredBackBufferRenderJob = None 100 self.blurredBackBufferAtlas = None 101 self.desktopBlurredBg = None 102 self._pickProjection = trinity.TriProjection() 103 self._pickView = trinity.TriView() 104 self._pickViewport = trinity.TriViewport() 105 self.cursorCache = {} 106 if not paparazziMode: 107 if IsMacOS(): 108 self.cursorSize = CursorSize.NORMAL 109 else: 110 self.cursorSize = cursor_size_setting.get() 111 cursor_size_setting.on_change.connect(self.OnCursorSizeChanged) 112 self.alignIslands = set() 113 from carbonui.uicore import uicore 114 uicore.uilib = self 115 trinity.fontMan.loadFlag = 32 116 if not paparazziMode: 117 self._SetupRenderJob() 118 glowEnabled = gfxsettings.Get(gfxsettings.GFX_SHADER_QUALITY) > gfxsettings.SHADER_MODEL_LOW 119 self.desktop = self.CreateRootObject('Desktop', renderJob=self.desktopRenderJob, isFullscreen=True, glowEnabled=glowEnabled) 120 uthread.new(self.EnableEventHandling) 121 from eve.client.script.ui.tooltips.tooltipHandler import TooltipHandler 122 self.tooltipHandler = TooltipHandler() 123 trinity.device.RegisterResource(self) 124 self._hoverThread = None 125 self.eventHandlerResolver = None 126 self.menuHandlerResolver = None 127 show_window_bg_blur_setting.on_change.connect(self.OnWindowBlurSettingChanged) 128 font_shadow_enabled_setting.on_change.connect(self._on_font_shadow_enabled_setting_changed) 129 130 def __del__(self, *args): 131 trinity.mainWindow.onMouseMove = None 132 trinity.mainWindow.onMouseDown = None 133 trinity.mainWindow.onMouseUp = None 134 trinity.mainWindow.onMouseWheel = None 135 trinity.mainWindow.onKeyDown = None 136 trinity.mainWindow.onKeyUp = None 137 trinity.mainWindow.onChar = None 138 if self.renderJob: 139 self.renderJob.UnscheduleRecurring() 140 141 def EnableEventHandling(self): 142 from carbonui.uicore import uicore 143 while not uicore.IsReady(): 144 blue.synchro.SleepWallclock(1) 145 146 trinity.mainWindow.onMouseMove = self._OnMouseMove 147 trinity.mainWindow.onMouseDown = self._OnMouseDown 148 trinity.mainWindow.onMouseUp = self._OnMouseUp 149 trinity.mainWindow.onMouseWheel = self._OnMouseWheel 150 trinity.mainWindow.onKeyDown = self._OnKeyDown 151 trinity.mainWindow.onKeyUp = self._OnKeyUp 152 trinity.mainWindow.onChar = self._OnChar 153 trinity.mainWindow.onFocusChange = self._OnFocusChange 154 trinity.mainWindow.onClose = self._OnClose 155 log.LogInfo('Uilib event handling enabled') 156 157 def OnInvalidate(self, *args): 158 self.cursorCache = {} 159 160 def OnCreate(self, *args): 161 uthread.new(self.PrepareBlurredBackBuffer) 162 163 def OnWindowBlurSettingChanged(self, *args): 164 self.PrepareBlurredBackBuffer() 165 166 def OnGraphicSettingsChanged(self, *args, **kwargs): 167 if self.desktop: 168 self.desktop.glowEnabled = gfxsettings.Get(gfxsettings.GFX_SHADER_QUALITY) > gfxsettings.SHADER_MODEL_LOW 169 170 def OnUIColorsChanged(self): 171 self.desktop.OnColorThemeChanged() 172 173 def OnFontSizeChanged(self): 174 self.desktop.OnGlobalFontSizeChanged() 175 176 def OnCursorSizeChanged(self, value): 177 self.cursorSize = value 178 179 def _on_font_shadow_enabled_setting_changed(self, value): 180 self.desktop.OnGlobalFontShadowChanged() 181 182 def CreateTexture(self, width, height): 183 tex = self.textureAtlas.CreateTexture(int(width), int(height)) 184 return tex 185 186 def CreateRootObject(self, name, width = None, height = None, depthMin = None, depthMax = None, isFullscreen = False, renderTarget = None, renderJob = None, **kwargs): 187 from carbonui.primitives.desktop import UIRoot 188 desktop = UIRoot(pos=(0, 189 0, 190 width or trinity.mainWindow.width, 191 height or trinity.mainWindow.height), name=name, depthMin=depthMin, depthMax=depthMax, isFullscreen=isFullscreen, renderTarget=renderTarget, renderJob=renderJob, **kwargs) 192 self.AddRootObject(desktop) 193 return desktop 194 195 def GetRenderJob(self): 196 return self.desktopRenderJob 197 198 def GetVideoJob(self): 199 return self.videoJob 200 201 def OnUIScalingChange(self, *args): 202 self.PrepareBlurredBackBuffer() 203 204 def PrepareBlurredBackBuffer(self): 205 if self.blurredBackBufferRenderJob: 206 renderJob = self.blurredBackBufferRenderJob 207 renderJob.enabled = True 208 for step in renderJob.steps[:]: 209 renderJob.steps.remove(step) 210 211 else: 212 renderJob = trinity.CreateRenderJob() 213 renderJob.name = 'Blurred Back Buffer' 214 renderJob.ScheduleRecurring(insertFront=True) 215 self.blurredBackBufferRenderJob = renderJob 216 gfxShaderSettingSupportsBlur = gfxsettings.Get(gfxsettings.GFX_SHADER_QUALITY) > gfxsettings.SHADER_MODEL_LOW 217 if not (show_window_bg_blur_setting.is_enabled() and gfxShaderSettingSupportsBlur): 218 if self.blurredBackBufferRenderJob: 219 self.blurredBackBufferRenderJob.enabled = False 220 return 221 backbuffer = trinity.device.GetRenderContext().GetDefaultBackBuffer() 222 self.spaceSceneBackBufferCopy = trinity.Tr2RenderTarget(trinity.mainWindow.width, trinity.mainWindow.height, 1, backbuffer.format) 223 self.spaceSceneBackBufferDownSizedCopy = trinity.Tr2RenderTarget(trinity.mainWindow.width / 4, trinity.mainWindow.height / 4, 1, trinity.PIXEL_FORMAT.B8G8R8X8_UNORM) 224 self.spaceSceneBackBufferDownSizedCopy.name = 'spaceSceneBackBufferDownSizedCopy' 225 step = trinity.TriStepResolve(self.spaceSceneBackBufferCopy, backbuffer) 226 step.name = 'Resolve back buffer' 227 renderJob.steps.append(step) 228 if self.desktopBlurredBg: 229 self.RemoveRootObject(self.desktopBlurredBg) 230 self.desktopBlurredBg.Close() 231 self.desktopBlurredBg = self.CreateRootObject(name='desktopBlurred', renderTarget=self.spaceSceneBackBufferCopy, renderJob=renderJob, isFullscreen=True) 232 self.desktopBlurredBg.renderObject.clearBackground = False 233 renderJob.PushDepthStencil().pushCurrent = False 234 renderJob.SetVariableStore('BlitCurrent', self.spaceSceneBackBufferCopy).name = 'Set BlitCurrent variable' 235 value = (1.0 / trinity.mainWindow.width, 236 1.0 / trinity.mainWindow.height, 237 trinity.mainWindow.width, 238 trinity.mainWindow.height) 239 renderJob.SetVariableStore('g_texelSize', value).name = 'Set g_texelSize variable' 240 renderJob.PushRenderTarget(self.spaceSceneBackBufferDownSizedCopy) 241 renderJob.Clear((0, 0, 0, 0)) 242 effect = trinity.Tr2Effect() 243 effect.effectFilePath = 'res:/Graphics/Effect/Managed/Space/PostProcess/ColorDownFilter4.fx' 244 renderJob.RenderEffect(effect) 245 renderJob.PopRenderTarget() 246 renderJob.PopDepthStencil() 247 textureRes = trinity.TriTextureRes() 248 textureRes.SetFromRenderTarget(self.spaceSceneBackBufferDownSizedCopy) 249 atlasTexture = trinity.Tr2AtlasTexture() 250 atlasTexture.textureRes = textureRes 251 self.blurredBackBufferAtlas = atlasTexture 252 sm.ScatterEvent('OnBlurredBufferCreated') 253 254 def _SetupRenderJob(self): 255 self.renderJob = trinity.CreateRenderJob() 256 self.renderJob.name = 'UI' 257 self.PrepareBlurredBackBuffer() 258 self.sceneViewStep = self.renderJob.SetView() 259 self.scaledViewportStep = self.renderJob.SetViewport() 260 self.sceneProjectionStep = self.renderJob.SetProjection() 261 videoJobStep = self.renderJob.RunJob() 262 videoJobStep.name = 'Videos' 263 self.videoJob = trinity.CreateRenderJob() 264 self.videoJob.name = 'Update videos job' 265 videoJobStep.job = self.videoJob 266 self.bracketCurveSet = trinity.TriCurveSet() 267 self.bracketCurveSet.Play() 268 self.renderJob.Update(self.bracketCurveSet).name = 'Update brackets' 269 self.renderJob.SetViewport() 270 self.renderJob.PythonCB(self.Update).name = 'Update uilib' 271 self.desktopRenderJob = trinity.CreateRenderJob() 272 self.desktopRenderJob.name = 'Desktop' 273 self.renderJob.steps.append(trinity.TriStepRunJob(self.desktopRenderJob)) 274 self.renderJob.ScheduleRecurring() 275 is_perforce_client = not blue.pyos.packaged 276 if is_perforce_client: 277 trinity.SetFpsEnabled(settings.public.ui.Get('isFpsRenderJobEnabled', is_perforce_client)) 278 279 def OnSessionChanged(self, isRemote, sess, change): 280 if 'userid' in change: 281 has_required_role = session.role & ROLE_GML 282 is_perforce_client = not blue.pyos.packaged 283 if has_required_role and settings.public.ui.Get('isFpsRenderJobEnabled', is_perforce_client): 284 trinity.SetFpsEnabled(True) 285 else: 286 trinity.SetFpsEnabled(False) 287 288 def _GetMouseTravel(self): 289 if self._mouseButtonStates.get(uiconst.MOUSELEFT, False): 290 x, y, z = self._mouseDownPosition[uiconst.MOUSELEFT] 291 return math.sqrt(abs((x - self.x) * (x - self.x) + (y - self.y) * (y - self.y))) 292 return 0 293 294 mouseTravel = property(_GetMouseTravel) 295 296 def _GetRightBtn(self): 297 return self._mouseButtonStates.get(uiconst.MOUSERIGHT, False) 298 299 rightbtn = property(_GetRightBtn) 300 301 def _GetLeftBtn(self): 302 return self._mouseButtonStates.get(uiconst.MOUSELEFT, False) 303 304 leftbtn = property(_GetLeftBtn) 305 306 def _GetMiddleBtn(self): 307 return self._mouseButtonStates.get(uiconst.MOUSEMIDDLE, False) 308 309 midbtn = property(_GetMiddleBtn) 310 311 def ReleaseObject(self, object): 312 try: 313 del self.renderObjectToPyObjectDict[object.renderObject] 314 except KeyError: 315 pass 316 317 def GetMouseOver(self): 318 if self._mouseOver: 319 mouseOver = self._mouseOver() 320 if mouseOver and not mouseOver.destroyed: 321 return mouseOver 322 self._mouseOver = None 323 from carbonui.uicore import uicore 324 return uicore.desktop 325 326 mouseOver = property(GetMouseOver) 327 328 def GetAuxMouseOver(self): 329 if self._auxMouseOverRO: 330 return self.GetPyObjectFromRenderObject(self._auxMouseOverRO()) 331 332 auxMouseOver = property(GetAuxMouseOver) 333 334 def CheckAppFocus(self, hasFocus): 335 from carbonui.uicore import uicore 336 if getattr(uicore, 'registry', None) is None: 337 return 338 uicore.UpdateCursor(self.GetMouseOver(), 1) 339 if hasFocus: 340 modal = uicore.registry.GetModalWindow() 341 if modal: 342 uicore.registry.SetFocus(modal) 343 else: 344 f = uicore.registry.GetFocus() 345 if (not f or f.destroyed) and self.appfocusitem and self.appfocusitem(): 346 f = self.appfocusitem() 347 if f is not None and not f.destroyed: 348 uicore.registry.SetFocus(f) 349 self.appfocusitem = None 350 else: 351 focus = uicore.registry.GetFocus() 352 if focus: 353 self.appfocusitem = weakref.ref(focus) 354 uicore.registry.SetFocus(None) 355 mouseCaptureItem = self.GetMouseCapture() 356 if mouseCaptureItem: 357 self.ReleaseCapture() 358 self.centerMouse = False 359 self._mouseButtonStates = {} 360 self._mouseDownPosition = {} 361 self._TryExecuteHandler(uiconst.UI_MOUSEUP, mouseCaptureItem, (uiconst.MOUSELEFT,)) 362 return 1 363 364 def CheckAccelerators(self, vkey, flag): 365 modkeys = self.GetModifierKeyState(vkey) 366 if self.CheckActiveWindowAccelerators(modkeys, vkey, flag): 367 return True 368 if self.CheckMappedAccelerators(modkeys, vkey, flag): 369 return True 370 if self.CheckDirectionalAccelerators(vkey): 371 return True 372 return False 373 374 def CheckActiveWindowAccelerators(self, modkeys, vkey, flag): 375 from carbonui.uicore import uicore 376 wnd = uicore.registry.GetActive() 377 if wnd and hasattr(wnd, 'OnShortcutKeyDown'): 378 return wnd.OnShortcutKeyDown(modkeys, vkey, flag) 379 return False 380 381 def GetModifierKeyState(self, vkey = None): 382 ret = [] 383 for key in uiconst.MODKEYS: 384 ret.append(trinity.app.Key(key) and key != vkey) 385 386 return tuple(ret) 387 388 def CheckMappedAccelerators(self, modkeys, vkey, flag): 389 from carbonui.uicore import uicore 390 if not uicore.commandHandler: 391 return False 392 ctrl = self.Key(uiconst.VK_CONTROL) 393 if not ctrl and (self._modkeysOff, vkey) in uicore.commandHandler.commandMap.accelerators: 394 cmd = uicore.commandHandler.commandMap.accelerators[self._modkeysOff, vkey] 395 if cmd.ignoreModifierKey: 396 if not cmd.repeatable and flag & 1073741824: 397 return False 398 sm.ScatterEvent('OnCommandExecuted', cmd.name) 399 ret = uicore.cmd.ExecuteCommand(cmd) 400 if ret: 401 return ret 402 if (modkeys, vkey) in uicore.commandHandler.commandMap.accelerators: 403 cmd = uicore.commandHandler.commandMap.accelerators[modkeys, vkey] 404 if not cmd.repeatable and flag & 1073741824: 405 return False 406 sm.ScatterEvent('OnCommandExecuted', cmd.name) 407 return uicore.cmd.ExecuteCommand(cmd) 408 return False 409 410 def CheckDirectionalAccelerators(self, vkey): 411 from carbonui.uicore import uicore 412 active = uicore.registry.GetActive() 413 focus = uicore.registry.GetFocus() 414 focusOrActive = focus or active 415 if vkey == uiconst.VK_UP and hasattr(focusOrActive, 'OnUp'): 416 uthread.pool('uisvc::CheckDirectionalAccelerators OnUp', focusOrActive.OnUp) 417 return True 418 if vkey == uiconst.VK_DOWN and hasattr(focusOrActive, 'OnDown'): 419 uthread.pool('uisvc::CheckDirectionalAccelerators OnDown', focusOrActive.OnDown) 420 return True 421 if vkey == uiconst.VK_LEFT and hasattr(focusOrActive, 'OnLeft'): 422 uthread.pool('uisvc::CheckDirectionalAccelerators OnLeft', focusOrActive.OnLeft) 423 return True 424 if vkey == uiconst.VK_RIGHT and hasattr(focusOrActive, 'OnRight'): 425 uthread.pool('uisvc::CheckDirectionalAccelerators OnRight', focusOrActive.OnRight) 426 return True 427 if vkey == uiconst.VK_HOME and hasattr(focusOrActive, 'OnHome'): 428 uthread.pool('uisvc::CheckDirectionalAccelerators OnHome', focusOrActive.OnHome) 429 return True 430 if vkey == uiconst.VK_END and hasattr(focusOrActive, 'OnEnd'): 431 uthread.pool('uisvc::CheckDirectionalAccelerators OnEnd', focusOrActive.OnEnd) 432 return True 433 434 def RegisterForTriuiEvents(self, msgIDlst, function, *args, **kw): 435 if type(msgIDlst) == int: 436 msgIDlst = [msgIDlst] 437 cookie = uthread.uniqueId() or uthread.uniqueId() 438 self._triuiRegs[cookie] = msgIDlst 439 ref = CallableWeakRef(function) 440 for id_ in msgIDlst: 441 self._triuiRegsByMsgID.setdefault(id_, {})[cookie] = (ref, args, kw) 442 443 log.LogInfo('RegisterForTriuiEvents', cookie, msgIDlst, function, args, kw) 444 return cookie 445 446 def UnregisterForTriuiEvents(self, cookie): 447 if cookie not in self._triuiRegs: 448 return 449 log.LogInfo('UnregisterForTriuiEvents', cookie) 450 try: 451 for msgID_ in self._triuiRegs[cookie]: 452 del self._triuiRegsByMsgID[msgID_][cookie] 453 454 del self._triuiRegs[cookie] 455 except KeyError as what: 456 log.LogError('UnregisterForTriuiEvents: Tried to kill unexisting registration?', cookie) 457 log.LogException() 458 459 @telemetry.ZONE_METHOD 460 def RegisterObject(self, pyObject, renderObject): 461 self.renderObjectToPyObjectDict[renderObject] = pyObject 462 463 def GetPyObjectFromRenderObject(self, RO): 464 pyObject = self.renderObjectToPyObjectDict.get(RO, None) 465 if pyObject and not pyObject.destroyed: 466 return pyObject 467 468 def AddRootObject(self, obj): 469 if obj.name in self.rootObjectsByName: 470 raise AttributeError('Root object already exists with this name (%s)' % obj.name) 471 self.rootObjectsByName[obj.name] = obj 472 if obj not in self.rootObjects: 473 self.rootObjects.append(obj) 474 475 def UpdateRootObjectSizes(self): 476 for obj in self.rootObjects: 477 obj.UpdateSize() 478 479 def RemoveRootObject(self, obj): 480 if obj.name in self.rootObjectsByName: 481 del self.rootObjectsByName[obj.name] 482 if obj in self.rootObjects: 483 self.rootObjects.remove(obj) 484 485 def FindRootObject(self, name): 486 return self.rootObjectsByName.get(name, None) 487 488 def AddMouseTargetObject(self, mouseTargetObject): 489 self._mouseTargetObject = mouseTargetObject 490 491 def GetMouseTargetObject(self): 492 if self._mouseTargetObject: 493 if self._mouseTargetObject.GetOwner(): 494 return self._mouseTargetObject 495 self._mouseTargetObject = None 496 497 @telemetry.ZONE_METHOD 498 def Update(self, *args): 499 try: 500 if getattr(self, 'updatingFromRoot', False): 501 return 502 vp = trinity.TriViewport() 503 vp.width = trinity.device.width 504 vp.height = trinity.device.height 505 self.scaledViewportStep.viewport = vp 506 self.cursorPos = trinity.mainWindow.GetCursorPos() 507 self.UpdateMouseOver() 508 if self.tooltipHandler: 509 self.tooltipHandler.RefreshTooltip() 510 for root in self.rootObjects: 511 root.UpdateAlignmentAsRoot('uilib.Update') 512 513 islands = self.alignIslands 514 self.alignIslands = set() 515 for island in islands: 516 if not island.destroyed: 517 island.UpdateAlignmentAsRoot('uilib.Update Islands') 518 519 except: 520 LogException() 521 raise 522 523 def SetSceneCamera(self, camera): 524 from eve.client.script.ui.camera.cameraBase import CameraBase 525 if isinstance(camera, CameraBase): 526 self.sceneViewStep.view = None 527 self.sceneViewStep.camera = camera._camera 528 self.sceneProjectionStep.projection = camera.projectionMatrix 529 else: 530 self.sceneViewStep.view = camera.viewMatrix 531 self.sceneViewStep.camera = None 532 self.sceneProjectionStep.projection = camera.projectionMatrix 533 534 def SetSceneView(self, view, projection): 535 self.sceneViewStep.camera = None 536 self.sceneViewStep.view = view 537 self.sceneProjectionStep.projection = projection 538 539 @telemetry.ZONE_METHOD 540 def UpdateMouseOver(self, *args): 541 from carbonui.uicore import uicore 542 pyObject = None 543 auxRenderObject = None 544 cursorX, cursorY = self.cursorPos 545 if 0 <= cursorX <= trinity.mainWindow.width and 0 <= cursorY <= trinity.mainWindow.height: 546 mouseTargetObject = self.GetMouseTargetObject() 547 if mouseTargetObject and mouseTargetObject.IsMouseHeadingTowards(): 548 return 549 triobj, pyObject = self.PickScreenPosition(int(uicore.ScaleDpi(self.x)), int(uicore.ScaleDpi(self.y))) 550 if getattr(triobj, 'auxMouseover', None): 551 auxRenderObject = triobj.auxMouseover 552 newMouseOver = pyObject or uicore.desktop 553 currentMouseOver = self.GetMouseOver() 554 currentAuxiliaryTooltip = getattr(self, 'auxiliaryTooltip', None) 555 if auxRenderObject: 556 self._auxMouseOverRO = weakref.ref(auxRenderObject) 557 pyAuxObject = self.GetPyObjectFromRenderObject(auxRenderObject) 558 if pyAuxObject and hasattr(pyAuxObject, 'GetAuxiliaryTooltip'): 559 self.auxiliaryTooltip = pyAuxObject.GetAuxiliaryTooltip() 560 self.auxiliaryTooltipPosition = pyAuxObject.GetAuxiliaryTooltipPosition() 561 else: 562 self.auxiliaryTooltip = None 563 self.auxiliaryTooltipPosition = None 564 else: 565 self.auxiliaryTooltip = None 566 self.auxiliaryTooltipPosition = None 567 self._auxMouseOverRO = None 568 mouseCaptureItem = self.GetMouseCapture() 569 if newMouseOver is not self.mouseOver: 570 self._mouseOver = weakref.ref(newMouseOver) 571 if currentMouseOver is not newMouseOver or currentAuxiliaryTooltip != self.auxiliaryTooltip: 572 self.FlagTooltipsDirty() 573 if not mouseCaptureItem and currentMouseOver is not newMouseOver: 574 if self._hoverThread: 575 self._hoverThread.kill() 576 uicore.HideHint() 577 from carbonui.primitives.dragdrop import DragDropObject 578 if currentMouseOver: 579 if uicore.IsDragging() and isinstance(currentMouseOver, DragDropObject) and uicore.dragObject is not currentMouseOver: 580 currentMouseOver.OnDragExit(uicore.dragObject, uicore.dragObject.dragData) 581 self.CheckCallbacks(newMouseOver, uiconst.UI_DRAGEXIT, (uicore.dragObject, uicore.dragObject.dragData)) 582 else: 583 self._Propagate(eventId=uiconst.UI_MOUSEEXIT, uiObject=currentMouseOver, stopper=newMouseOver) 584 if newMouseOver: 585 if uicore.IsDragging() and isinstance(newMouseOver, DragDropObject) and uicore.dragObject is not newMouseOver: 586 newMouseOver.OnDragEnter(uicore.dragObject, uicore.dragObject.dragData) 587 self.CheckCallbacks(newMouseOver, uiconst.UI_DRAGENTER, (uicore.dragObject, uicore.dragObject.dragData)) 588 else: 589 self._Propagate(eventId=uiconst.UI_MOUSEENTER, uiObject=newMouseOver, stopper=currentMouseOver) 590 hoverHandlerArgs, hoverHandler = self.FindEventHandler(newMouseOver, self.EVENTMAP[uiconst.UI_MOUSEHOVER]) 591 if hoverHandler: 592 self._hoverThread = uthread.new(self._HoverThread) 593 uicore.CheckCursor() 594 595 def PickScreenPosition(self, x, y): 596 triobj = None 597 pyObject = None 598 for root in self.rootObjects: 599 if not root.pickState: 600 continue 601 RO = root.GetRenderObject() 602 if not RO: 603 continue 604 camera = root.GetCamera() 605 if root.renderTargetStep: 606 pass 607 elif camera: 608 triobj = RO.PickObject(x, y, camera.projectionMatrix, camera.viewMatrix, trinity.device.viewport) 609 elif hasattr(root, 'PickObject'): 610 triobj = root.PickObject(x, y) 611 else: 612 triobj = RO.PickObject(x, y, self._pickProjection, self._pickView, self._pickViewport) 613 if triobj: 614 pyObject = self.GetPyObjectFromRenderObject(triobj) 615 if pyObject: 616 overridePick = getattr(pyObject, 'OverridePick', None) 617 if overridePick: 618 overrideObject = overridePick(x, y) 619 if overrideObject: 620 pyObject = overrideObject 621 from carbonui.control.layer import LayerCore 622 if pyObject and not isinstance(pyObject, LayerCore): 623 break 624 625 return (triobj, pyObject) 626 627 def FlagTooltipsDirty(self, instant = False): 628 if self.tooltipHandler: 629 self.tooltipHandler.FlagTooltipsDirty(instant) 630 631 UpdateTooltip = FlagTooltipsDirty 632 633 def RefreshTooltipForOwner(self, owner): 634 if self.tooltipHandler: 635 self.tooltipHandler.RefreshTooltipForOwner(owner) 636 637 def _OnMouseMove(self, left, top): 638 from carbonui.uicore import uicore 639 with uthread.BlockTrapSection(): 640 currentMouseOver = self.GetMouseOver() 641 mouseX = uicore.ReverseScaleDpi(left) 642 mouseY = uicore.ReverseScaleDpi(top) 643 if self.desktop: 644 self.desktop.glowHighlightCoords = (left, top) 645 if self.x != mouseX or self.y != mouseY: 646 self.dx = mouseX - self.x 647 self.dy = mouseY - self.y 648 self.x = mouseX 649 self.y = mouseY 650 self.z = 0 651 if self.centerMouse: 652 self.SetCursorPos(uicore.desktop.width / 2, uicore.desktop.height / 2) 653 mouseCaptureItem = self.GetMouseCapture() 654 if mouseCaptureItem: 655 self._TryExecuteHandler(uiconst.UI_MOUSEMOVE, mouseCaptureItem) 656 self._TryExecuteHandler(uiconst.UI_MOUSEMOVEDRAG, mouseCaptureItem) 657 elif currentMouseOver: 658 self._TryExecuteHandler(uiconst.UI_MOUSEMOVE, currentMouseOver) 659 self._TryExecuteHandler(uiconst.UI_MOUSEMOVEDRAG, currentMouseOver) 660 661 def _OnMouseDown(self, button, left, top): 662 with uthread.BlockTrapSection(): 663 if button == uiconst.MOUSELEFT: 664 self._OnLeftMouseDown() 665 elif button == uiconst.MOUSEMIDDLE: 666 self._OnMiddleMouseDown() 667 elif button == uiconst.MOUSERIGHT: 668 self._OnRightMouseDown() 669 elif button in (uiconst.MOUSEXBUTTON1, uiconst.MOUSEXBUTTON2): 670 self._OnOtherMouseDown(button) 671 672 def _OnLeftMouseDown(self): 673 from carbonui.uicore import uicore 674 button = uiconst.MOUSELEFT 675 currentMouseOver = self.GetMouseOver() 676 self._clickCount += 1 677 self._clickTimer = AutoTimer(CLICKCOUNTRESETTIME, self.ResetClickCounter) 678 self._expandMenu = button 679 self._mouseButtonStates[button] = True 680 self._mouseDownPosition[button] = (self.x, self.y, self.z) 681 if self.exclusiveMouseFocusActive: 682 self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, self.GetMouseCapture(), (button,), param=(button,)) 683 self._TryExecuteHandler(uiconst.UI_MOUSEDOWNDRAG, self.GetMouseCapture(), (button,), param=(button,)) 684 else: 685 self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, currentMouseOver, (button,), param=(button,)) 686 self._TryExecuteHandler(uiconst.UI_MOUSEDOWNDRAG, currentMouseOver, (button,), param=(button,)) 687 self.SetCapture(currentMouseOver, retainFocus=self.exclusiveMouseFocusActive) 688 if not currentMouseOver.IsUnder(uicore.layer.menu): 689 from carbonui.control.contextMenu.menuUtil import CloseContextMenus 690 CloseContextMenus() 691 currentFocus = uicore.registry.GetFocus() 692 if currentFocus != currentMouseOver: 693 uicore.registry.SetFocus(currentMouseOver) 694 695 def _OnMiddleMouseDown(self): 696 currentMouseOver = self.GetMouseOver() 697 button = uiconst.MOUSEMIDDLE 698 self._expandMenu = None 699 self._mouseButtonStates[button] = True 700 self._mouseDownPosition[button] = (self.x, self.y, self.z) 701 self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, currentMouseOver, (button,), param=(button,)) 702 uthread.new(self.CheckAccelerators, uiconst.VK_MBUTTON, 0) 703 704 def _OnRightMouseDown(self): 705 from carbonui.uicore import uicore 706 currentMouseOver = self.GetMouseOver() 707 button = uiconst.MOUSERIGHT 708 self._expandMenu = button 709 self._mouseButtonStates[button] = True 710 self._mouseDownPosition[button] = (self.x, self.y, self.z) 711 if self.exclusiveMouseFocusActive: 712 self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, self.GetMouseCapture(), (button,), param=(button,)) 713 else: 714 self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, currentMouseOver, (button,), param=(button,)) 715 if not currentMouseOver.IsUnder(uicore.layer.menu): 716 from carbonui.control.contextMenu.menuUtil import CloseContextMenus 717 CloseContextMenus() 718 currentFocus = uicore.registry.GetFocus() 719 if currentFocus is not currentMouseOver: 720 uicore.registry.SetFocus(currentMouseOver) 721 722 def _OnOtherMouseDown(self, button): 723 currentMouseOver = self.GetMouseOver() 724 self._mouseButtonStates[button] = True 725 self._TryExecuteHandler(uiconst.UI_MOUSEDOWN, currentMouseOver, (button,), param=(button,)) 726 acc = uiconst.VK_XBUTTON1 if button == uiconst.MOUSEXBUTTON1 else uiconst.VK_XBUTTON2 727 uthread.new(self.CheckAccelerators, acc, 0) 728 729 def _OnMouseUp(self, button, left, top): 730 with uthread.BlockTrapSection(): 731 if button == uiconst.MOUSELEFT: 732 self._OnLeftMouseUp() 733 elif button == uiconst.MOUSERIGHT: 734 self._OnRightMouseUp() 735 elif button in (uiconst.MOUSEMIDDLE, uiconst.MOUSEXBUTTON1, uiconst.MOUSEXBUTTON2): 736 self._OnOtherMouseUp(button) 737 738 def _OnLeftMouseUp(self): 739 currentMouseOver = self.GetMouseOver() 740 button = uiconst.MOUSELEFT 741 self._mouseButtonStates[button] = False 742 mouseCaptureItem = self.GetMouseCapture() 743 if mouseCaptureItem: 744 if not self.exclusiveMouseFocusActive: 745 if getattr(mouseCaptureItem, 'expandOnLeft', 0) and not self.rightbtn and self._expandMenu == button and self.FindMenuHandler(mouseCaptureItem): 746 x, y, z = self._mouseDownPosition[button] 747 if abs(self.x - x) < 3 and abs(self.y - y) < 3: 748 self.FlagTooltipsDirty(True) 749 uthread.new(carbonui.control.contextMenu.contextMenu.ShowMenu, mouseCaptureItem, self.GetAuxMouseOver()) 750 self._expandMenu = False 751 self._TryExecuteHandler(uiconst.UI_MOUSEUP, mouseCaptureItem, (button,), param=(button, 0)) 752 if not self.exclusiveMouseFocusActive: 753 self.ReleaseCapture() 754 if currentMouseOver is not mouseCaptureItem: 755 self._Propagate(eventId=uiconst.UI_MOUSEEXIT, uiObject=mouseCaptureItem, stopper=currentMouseOver) 756 self._Propagate(eventId=uiconst.UI_MOUSEENTER, uiObject=currentMouseOver, stopper=mouseCaptureItem) 757 else: 758 self._TryExecuteClickHandler(0, 0) 759 760 def _OnRightMouseUp(self): 761 currentMouseOver = self.GetMouseOver() 762 button = uiconst.MOUSERIGHT 763 self._mouseButtonStates[button] = False 764 if self.exclusiveMouseFocusActive: 765 self._TryExecuteHandler(uiconst.UI_MOUSEUP, self.GetMouseCapture(), (button,), param=(button, 0)) 766 else: 767 if not self.leftbtn and self._expandMenu == button and (self.FindMenuHandler(currentMouseOver) or self._auxMouseOverRO is not None): 768 x, y, z = self._mouseDownPosition[button] 769 if abs(self.x - x) < 3 and abs(self.y - y) < 3: 770 self.FlagTooltipsDirty(True) 771 uthread.new(carbonui.control.contextMenu.contextMenu.ShowMenu, currentMouseOver, self.GetAuxMouseOver()) 772 self._expandMenu = None 773 self._TryExecuteHandler(uiconst.UI_MOUSEUP, currentMouseOver, (button,), param=(button, 0)) 774 775 def _OnOtherMouseUp(self, button): 776 self._mouseButtonStates[button] = False 777 self._TryExecuteHandler(uiconst.UI_MOUSEUP, self.GetMouseOver(), (button,), param=(button, 0)) 778 779 def _OnMouseWheel(self, delta): 780 from carbonui.uicore import uicore 781 with uthread.BlockTrapSection(): 782 mouseZ = delta 783 self.dz = mouseZ 784 if self.mouseOver: 785 mouseOver = self.mouseOver 786 wasHandled = False 787 while mouseOver.parent and mouseOver != uicore.uilib.desktop: 788 mwHandlerArgs, mwHandler = self.FindEventHandler(mouseOver, 'OnMouseWheel') 789 if mwHandler: 790 args = [mouseZ] + list(mwHandlerArgs[:]) 791 wasHandled = mwHandler(*args) 792 if wasHandled != False: 793 break 794 mouseOver = mouseOver.parent 795 796 handlerObject = mouseOver if wasHandled else None 797 self.CheckCallbacks(handlerObject, uiconst.UI_MOUSEWHEEL, (mouseZ,)) 798 799 def _OnKeyDown(self, key, flags): 800 from carbonui.uicore import uicore 801 with uthread.BlockTrapSection(): 802 focus = uicore.registry.GetFocus() 803 if focus: 804 self._TryExecuteHandler(uiconst.UI_KEYDOWN, focus, (key, flags), param=(key, flags)) 805 else: 806 self.CheckCallbacks(None, uiconst.UI_KEYDOWN, (key, flags)) 807 self._keyDownAcceleratorThread = uthread.new(self.CheckAccelerators, key, flags) 808 809 def _OnKeyUp(self, key, flags): 810 from carbonui.uicore import uicore 811 with uthread.BlockTrapSection(): 812 focus = uicore.registry.GetFocus() 813 if focus: 814 self._TryExecuteHandler(uiconst.UI_KEYUP, focus, (key, flags), param=(key, flags)) 815 else: 816 self.CheckCallbacks(None, uiconst.UI_KEYUP, (key, flags)) 817 if key == uiconst.VK_SNAPSHOT and uicore.commandHandler: 818 uicore.commandHandler.PrintScreen() 819 820 def _OnChar(self, key, flags, isDead): 821 from carbonui.uicore import uicore 822 with uthread.BlockTrapSection(): 823 if isDead: 824 focus = uicore.registry.GetFocus() 825 if focus and focus.HasEventHandler('OnChar') and focus.IsVisible(): 826 self.StopKeyDownAcceleratorThread() 827 else: 828 self.ignoreDeadChar = key 829 else: 830 char = key 831 ignoreChar = False 832 if char <= 32 or char == self.ignoreDeadChar: 833 ctrl = trinity.app.Key(uiconst.VK_CONTROL) 834 if char not in (uiconst.VK_RETURN, uiconst.VK_BACK, uiconst.VK_SPACE) or ctrl: 835 ignoreChar = True 836 if not ignoreChar: 837 calledOn = self.ResolveOnChar(key, flags) 838 if calledOn: 839 self.StopKeyDownAcceleratorThread() 840 self.ignoreDeadChar = None 841 842 def _OnFocusChange(self, hasFocus): 843 from carbonui.uicore import uicore 844 with uthread.BlockTrapSection(): 845 self.CheckAppFocus(hasFocus=hasFocus) 846 self.CheckCallbacks(obj=uicore.registry.GetFocus(), msgID=uiconst.UI_ACTIVE, param=(hasFocus,)) 847 sm.ScatterEvent('OnApplicationFocusChanged', hasFocus) 848 849 def _OnClose(self): 850 from carbonui.uicore import uicore 851 with uthread.BlockTrapSection(): 852 if uicore.commandHandler: 853 uthread.new(uicore.commandHandler.CmdQuitGame) 854 return False 855 return True 856 857 def CheckCallbacks(self, obj, msgID, param): 858 for cookie, (wr, args, kw) in self._triuiRegsByMsgID.get(msgID, {}).items(): 859 try: 860 if not wr() or not wr()(*(args + (obj, msgID, param)), **kw): 861 self.UnregisterForTriuiEvents(cookie) 862 except UserError as what: 863 864 def f(): 865 raise what 866 867 uthread.new(f) 868 except: 869 log.LogError('OnAppEvent (cookie', cookie, '): Exception when trying to process callback!') 870 log.LogException() 871 872 def StopKeyDownAcceleratorThread(self): 873 if self._keyDownAcceleratorThread: 874 self._keyDownAcceleratorThread.kill() 875 876 def ResetClickCounter(self, *args): 877 self._clickTimer = None 878 self._clickCount = 0 879 880 def GetClickCounter(self): 881 return (self._clickCount - 1) % 3 + 1 882 883 def ResolveOnChar(self, char, flag): 884 ignore = (uiconst.VK_RETURN, uiconst.VK_BACK) 885 if char < 32 and char not in ignore: 886 return False 887 from carbonui.uicore import uicore 888 focus = uicore.registry.GetFocus() 889 if focus and focus.HasEventHandler('OnChar') and focus.IsVisible(): 890 _, handler = self.FindEventHandler(focus, 'OnChar') 891 handled = handler(char, flag) 892 if handled: 893 return focus 894 895 def _TryExecuteClickHandler(self, wParam, lParam): 896 currentMouseOver = self.GetMouseOver() 897 if self._clickCount > 1: 898 clickObject = self.GetClickObject() 899 if clickObject is None: 900 self.ResetClickCounter() 901 return 902 x, y = self._clickPosition 903 distanceOK = abs(self.x - x) < 5 and abs(self.y - y) < 5 904 clickPosOK = clickObject is currentMouseOver and distanceOK 905 dblHandlerArgs, dblHandler = self.FindEventHandler(clickObject, 'OnDblClick') 906 tripHandlerArgs, tripleHandler = self.FindEventHandler(clickObject, 'OnTripleClick') 907 if self._clickCount == 2 and dblHandler and clickPosOK: 908 self._TryExecuteHandler(uiconst.UI_DBLCLICK, currentMouseOver) 909 elif self._clickCount == 3 and tripleHandler and clickPosOK: 910 self._TryExecuteHandler(uiconst.UI_TRIPLECLICK, currentMouseOver) 911 else: 912 self._clickCount = 1 913 if self._clickCount <= 1: 914 handlerArgs, handler = self.FindEventHandler(currentMouseOver, 'OnClick') 915 if handler: 916 self._TryExecuteHandler(uiconst.UI_CLICK, currentMouseOver) 917 self.SetClickObject(currentMouseOver) 918 self._clickPosition = (self.x, self.y) 919 920 def _TryExecuteHandler(self, eventID, uiObject, eventArgs = None, param = None): 921 itemCapturingMouse = self.GetMouseCapture() 922 if itemCapturingMouse: 923 uiObject = itemCapturingMouse 924 handled = self._ExecuteHandlerRaw(eventID, uiObject, eventArgs) 925 handlerObject = uiObject if handled else None 926 self.CheckCallbacks(handlerObject, eventID, param) 927 return handlerObject 928 929 def _ExecuteHandlerRaw(self, eventID, uiObject, arguments = None): 930 functionName = self.EVENTMAP.get(eventID, None) 931 if functionName is None: 932 raise NotImplementedError 933 handlerArgs, handler = self.FindEventHandler(uiObject, functionName) 934 if not handler: 935 return False 936 args = handlerArgs[:] 937 if arguments: 938 args += arguments 939 if eventID in self.UTHREADEDEVENTS: 940 uthread.new(handler, *args) 941 else: 942 try: 943 handler(*args) 944 except Exception: 945 log.LogException() 946 raise 947 948 return True 949 950 def SetWindowOrder(self, *args): 951 return trinity.app.uilib.SetWindowOrder(*args) 952 953 def FindEventHandler(self, uiObject, handlerName): 954 if getattr(self, 'eventHandlerResolver', None): 955 return self.eventHandlerResolver(uiObject, handlerName) 956 else: 957 return uiObject.FindEventHandler(handlerName) 958 959 def GetEventHandlerResolver(self): 960 return self.eventHandlerResolver 961 962 def SetEventHandlerResolver(self, resolver): 963 self.eventHandlerResolver = resolver 964 965 def FindMenuHandler(self, uiObject): 966 if getattr(self, 'menuHandlerResolver', None): 967 return self.menuHandlerResolver(uiObject) 968 else: 969 return getattr(uiObject, 'GetMenu', None) 970 971 def GetMenuHandlerResolver(self): 972 return self.menuHandlerResolver 973 974 def SetMenuHandlerResolver(self, resolver): 975 self.menuHandlerResolver = resolver 976 977 def GetMouseButtonState(self, buttonFlag): 978 return self._mouseButtonStates.get(buttonFlag, False) 979 980 def Key(self, vkey): 981 return trinity.app.Key(vkey) 982 983 def SetCursorProperties(self, cursor): 984 trinity.mainWindow.mouseCursor = cursor 985 986 def SetCursorPos(self, x, y): 987 self.x = x 988 self.y = y 989 from carbonui.uicore import uicore 990 return trinity.app.SetCursorPos(uicore.ScaleDpi(x), uicore.ScaleDpi(y)) 991 992 def GetCursorPath(self): 993 pass 994 995 def SetCursor(self, cursorResPath): 996 if self.exclusiveMouseFocusActive: 997 return 998 if self.cursorSize != CursorSize.NORMAL: 999 cursorResPath = uiconst.UICURSOR_REPRESENTATIONS[cursorResPath][self.cursorSize - 1] 1000 if not blue.paths.exists(cursorResPath): 1001 raise RuntimeError('Cursor not found: %s' % cursorResPath) 1002 cursor = self.cursorCache.get(cursorResPath, None) 1003 if cursor is None: 1004 cursor = self._ConstructCursor(cursorResPath) 1005 self.SetCursorProperties(cursor) 1006 1007 def _ConstructCursor(self, cursorResPath): 1008 representations = [] 1009 for each in uiconst.UICURSOR_REPRESENTATIONS.get(cursorResPath, ()): 1010 bmp = trinity.Tr2HostBitmap() 1011 bmp.CreateFromFile(each) 1012 representations.append(bmp) 1013 1014 bmp = trinity.Tr2HostBitmap() 1015 bmp.CreateFromFile(cursorResPath) 1016 center_x = 16 1017 center_y = 15 1018 if self.cursorSize == CursorSize.LARGE: 1019 center_x = 32 1020 center_y = 31 1021 elif self.cursorSize == CursorSize.EXTRA_LARGE: 1022 center_x = 48 1023 center_y = 47 1024 cursor = trinity.Tr2MouseCursor(bmp, center_x, center_y, representations) 1025 self.cursorCache[cursorResPath] = cursor 1026 return cursor 1027 1028 def FindWindow(self, wndName, fromParent): 1029 return trinity.app.uilib.FindWindow(wndName, fromParent) 1030 1031 def SetMouseCapture(self, item, retainFocus = False): 1032 self._capturingMouseItem = weakref.ref(item) 1033 self.exclusiveMouseFocusActive = retainFocus 1034 self.FlagTooltipsDirty() 1035 1036 SetCapture = SetMouseCapture 1037 1038 def GetMouseCapture(self): 1039 if self._capturingMouseItem: 1040 captureItem = self._capturingMouseItem() 1041 if captureItem and not captureItem.destroyed: 1042 return captureItem 1043 self._capturingMouseItem = None 1044 self.exclusiveMouseFocusActive = False 1045 1046 GetCapture = GetMouseCapture 1047 capture = property(GetMouseCapture) 1048 1049 def SetClickObject(self, item): 1050 self._clickItem = weakref.ref(item) 1051 1052 def GetClickObject(self): 1053 if self._clickItem: 1054 clickObject = self._clickItem() 1055 if clickObject and not clickObject.destroyed: 1056 return clickObject 1057 1058 def ReleaseCapture(self, itemReleasing = None): 1059 self._capturingMouseItem = None 1060 self.exclusiveMouseFocusActive = False 1061 self.FlagTooltipsDirty() 1062 from carbonui.uicore import uicore 1063 uicore.UpdateCursor(uicore.uilib.mouseOver) 1064 1065 def ClipCursor(self, *rect): 1066 from carbonui.uicore import uicore 1067 self._cursorClip = rect 1068 l, t, r, b = rect 1069 trinity.app.ClipCursor(uicore.ScaleDpi(l), uicore.ScaleDpi(t), uicore.ScaleDpi(r), uicore.ScaleDpi(b)) 1070 1071 def UnclipCursor(self, *args): 1072 self._cursorClip = None 1073 trinity.app.UnclipCursor() 1074 1075 def _HoverThread(self): 1076 while True: 1077 if trinity.app.IsHidden(): 1078 return 1079 blue.synchro.SleepWallclock(HOVERTIME) 1080 self._TryExecuteHandler(uiconst.UI_MOUSEHOVER, self.mouseOver) 1081 1082 def _Propagate(self, eventId, uiObject, arguments = None, globalArguments = None, stopper = None): 1083 firstHandler = None 1084 while uiObject: 1085 if uiObject in self.rootObjects: 1086 break 1087 if uiObject is stopper or stopper.IsUnder(uiObject): 1088 break 1089 handled = self._ExecuteHandlerRaw(eventId, uiObject, arguments) 1090 if handled and firstHandler is None: 1091 firstHandler = uiObject 1092 uiObject = uiObject.parent 1093 1094 self.CheckCallbacks(firstHandler, eventId, globalArguments)