From 47941cc8d5c6aa600b603b203a430b60e0d04900 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Parodi=2C=20Eugenio=20=F0=9F=8C=B6?= Date: Wed, 18 Feb 2026 08:48:41 +0000 Subject: [PATCH] chore: reimplement the mouse release workaround --- apps/ttkode/ttkode/app/ttkode.py | 18 ++++++++++++++++-- demo/showcase/tab.py | 6 ++++++ libs/pyTermTk/TermTk/TTkCore/ttk.py | 9 +++++---- libs/pyTermTk/TermTk/TTkWidgets/container.py | 10 ++++++++++ .../TermTk/TTkWidgets/rootcontainer.py | 11 +++++++++++ libs/pyTermTk/TermTk/TTkWidgets/widget.py | 13 +++++++------ 6 files changed, 55 insertions(+), 12 deletions(-) diff --git a/apps/ttkode/ttkode/app/ttkode.py b/apps/ttkode/ttkode/app/ttkode.py index b96c9227..27d11649 100644 --- a/apps/ttkode/ttkode/app/ttkode.py +++ b/apps/ttkode/ttkode/app/ttkode.py @@ -75,9 +75,23 @@ class _TextDocument(ttk.TextDocumentHighlight): def getTabButtonStyle(self) -> dict: if self._changedStatus: - return {'default':{'closeGlyph':' ● '}} + return { + 'default':{ + 'closeGlyph': { + 'default':' ● ', + 'hovered':' ● ' + } + } + } else: - return {'default':{'closeGlyph':' □ '}} + return { + 'default':{ + 'closeGlyph': { + 'default':' ○ ', + 'hovered':' ○ ' + } + } + } def _handleContentChanged(self) -> None: '''A signal is emitted when the file status change, marking it as modified or not''' diff --git a/demo/showcase/tab.py b/demo/showcase/tab.py index 6f893d9a..da7064f1 100755 --- a/demo/showcase/tab.py +++ b/demo/showcase/tab.py @@ -53,6 +53,12 @@ def demoTab(root=None, border=True): tabWidget1.addMenu("ZZ", ttk.TTkK.RIGHT) tabWidget1.addMenu("KK", ttk.TTkK.RIGHT) + @ttk.pyTTkSlot(int) + def _reportClose(num:int): + tabWidget1.removeTab(num) + + tabWidget1.tabCloseRequested.connect(_reportClose) + return tabWidget1 def main(): diff --git a/libs/pyTermTk/TermTk/TTkCore/ttk.py b/libs/pyTermTk/TermTk/TTkCore/ttk.py index 479b0385..a171bf5e 100644 --- a/libs/pyTermTk/TermTk/TTkCore/ttk.py +++ b/libs/pyTermTk/TermTk/TTkCore/ttk.py @@ -329,11 +329,12 @@ class TTk(_TTkRootContainer): focusWidget.mouseEvent(nmevt) else: # Sometimes the release event is not retrieved - if ( focusWidget and - focusWidget._pendingMouseRelease and + if ( ( _pmr:=self._getPendingMouseReleaseWidget() ) and not TTkHelper.isDnD() ): - focusWidget.mouseEvent(mevt.clone(evt=TTkK.Release)) - focusWidget._pendingMouseRelease = False + x,y = TTkHelper.absPos(_pmr) + rmevt = mevt.clone(evt=TTkK.Release, pos=(mevt.x-x, mevt.y-y)) + _pmr.mouseEvent(rmevt) + self._setPendingMouseReleaseWidget(None) # Adding this Crappy logic to handle a corner case in the drop routine # where the mouse is leaving any widget able to handle the drop event if not self.mouseEvent(mevt): diff --git a/libs/pyTermTk/TermTk/TTkWidgets/container.py b/libs/pyTermTk/TermTk/TTkWidgets/container.py index 3873436b..138a8330 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/container.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/container.py @@ -155,6 +155,16 @@ class TTkContainer(TTkWidget): self._layout.setParent(self) self.update(updateLayout=True) + def _getPendingMouseReleaseWidget(self) -> Optional[TTkWidget]: + if (_pw:=self.parentWidget()): + return _pw._getPendingMouseReleaseWidget() + return None + + def _setPendingMouseReleaseWidget(self, widget:Optional[TTkWidget]) -> None: + if not (_pw:=self.parentWidget()): + return + _pw._setPendingMouseReleaseWidget(widget) + def _getFocusWidget(self) -> Optional[TTkWidget]: if (_pw:=self.parentWidget()): return _pw._getFocusWidget() diff --git a/libs/pyTermTk/TermTk/TTkWidgets/rootcontainer.py b/libs/pyTermTk/TermTk/TTkWidgets/rootcontainer.py index b333cb33..6adcd47e 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/rootcontainer.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/rootcontainer.py @@ -71,17 +71,28 @@ class _TTkRootContainer(TTkContainer): consumes the event, ensuring focus loops back to the first/last focusable widget. ''' __slots__ = ( + '_pendingMouseReleaseWidget', '_focusWidget', '_overlay') + _pendingMouseReleaseWidget:Optional[TTkWidget] _focusWidget:Optional[TTkWidget] _overlay:List[_TTkOverlay] def __init__(self, **kwargs) -> None: + self._pendingMouseReleaseWidget = None self._focusWidget = None self._overlay = [] super().__init__(**kwargs) + def _getPendingMouseReleaseWidget(self) -> Optional[TTkWidget]: + return self._pendingMouseReleaseWidget + + def _setPendingMouseReleaseWidget(self, widget:Optional[TTkWidget]) -> None: + if self._pendingMouseReleaseWidget is widget: + return + self._pendingMouseReleaseWidget = widget + def _getFocusWidget(self) -> Optional[TTkWidget]: ''' Returns the currently focused widget. diff --git a/libs/pyTermTk/TermTk/TTkWidgets/widget.py b/libs/pyTermTk/TermTk/TTkWidgets/widget.py index d3868fc4..8ca5d980 100644 --- a/libs/pyTermTk/TermTk/TTkWidgets/widget.py +++ b/libs/pyTermTk/TermTk/TTkWidgets/widget.py @@ -113,7 +113,6 @@ class TTkWidget(TMouseEvents, TKeyEvents, TDragEvents): '_focus_policy', '_canvas', '_widgetItem', '_visible', - '_pendingMouseRelease', '_enabled', '_style', '_currentStyle', '_toolTip', @@ -136,7 +135,6 @@ class TTkWidget(TMouseEvents, TKeyEvents, TDragEvents): _canvas:TTkCanvas _widgetItem:TTkWidgetItem _visible:bool - _pendingMouseRelease:bool _enabled:bool _style:Dict _currentStyle:Dict @@ -230,7 +228,6 @@ class TTkWidget(TMouseEvents, TKeyEvents, TDragEvents): self._name = name if name else self.__class__.__name__ self._parent = parent - self._pendingMouseRelease = False self._x, self._y = pos if pos else (x,y) self._width, self._height = size if size else (width,height) @@ -510,7 +507,6 @@ class TTkWidget(TMouseEvents, TKeyEvents, TDragEvents): TTkHelper.toolTipClose() if evt.evt == TTkK.Release: - self._pendingMouseRelease = False self._processStyleEvent(TTkWidget._S_NONE) if self.mouseReleaseEvent(evt): return True @@ -525,13 +521,12 @@ class TTkWidget(TMouseEvents, TKeyEvents, TDragEvents): w.setFocus() w.raiseWidget() if evt.tap == 2 and self.mouseDoubleClickEvent(evt): - #self._pendingMouseRelease = True return True if evt.tap > 1 and self.mouseTapEvent(evt): return True if evt.tap == 1 and self.mousePressEvent(evt): # TTkLog.debug(f"Click {self._name}") - self._pendingMouseRelease = True + self._setPendingMouseRelease() return True if evt.key == TTkK.Wheel: @@ -705,6 +700,12 @@ class TTkWidget(TMouseEvents, TKeyEvents, TDragEvents): if updateParent and self._parent is not None: self._parent.update(updateLayout=True) + def _setPendingMouseRelease(self) -> None: + '''Focus the widget''' + if not (_p:=self._parent): + return + _p._setPendingMouseReleaseWidget(self) + @pyTTkSlot() def setFocus(self) -> None: '''Focus the widget'''