diff --git a/gui/utils/clipboard.py b/gui/utils/clipboard.py index a8db13ca7..d4b7bf33f 100644 --- a/gui/utils/clipboard.py +++ b/gui/utils/clipboard.py @@ -1,68 +1,20 @@ # noinspection PyPackageRequirements -import wx +import pyclip from logbook import Logger logger = Logger(__name__) def toClipboard(text): - """ - Copy text to clipboard. Explicitly uses CLIPBOARD selection, not PRIMARY. - - On X11 systems, wxPython can confuse between PRIMARY and CLIPBOARD selections, - causing "already open" errors. This function ensures we always use CLIPBOARD. - - See: https://discuss.wxpython.org/t/wx-theclipboard-pasting-different-content-on-every-second-paste/35361 - """ - clipboard = wx.TheClipboard - try: - # Explicitly use CLIPBOARD selection, not PRIMARY selection - # This prevents X11 confusion between the two clipboard types - clipboard.UsePrimarySelection(False) - - if clipboard.Open(): - try: - data = wx.TextDataObject(text) - clipboard.SetData(data) - return True - finally: - clipboard.Close() - else: - logger.debug("Failed to open clipboard for writing") - return False - except Exception as e: - logger.warning("Error writing to clipboard: {}", e) - return False + pyclip.copy(text) def fromClipboard(): """ - Read text from clipboard. Explicitly uses CLIPBOARD selection, not PRIMARY. - - On X11 systems, wxPython can confuse between PRIMARY and CLIPBOARD selections, - causing "already open" errors. This function ensures we always use CLIPBOARD. - - See: https://discuss.wxpython.org/t/wx-theclipboard-pasting-different-content-on-every-second-paste/35361 + Read text from clipboard. Uses pyclip to grab in a cross-platform, reliable manner. """ - clipboard = wx.TheClipboard - try: - # Explicitly use CLIPBOARD selection, not PRIMARY selection - # This prevents X11 confusion between the two clipboard types - clipboard.UsePrimarySelection(False) - - if clipboard.Open(): - try: - data = wx.TextDataObject() - if clipboard.GetData(data): - return data.GetText() - else: - logger.debug("Clipboard open but no CLIPBOARD data available") - return None - finally: - clipboard.Close() - else: - logger.debug("Failed to open clipboard for reading") - return None - except Exception as e: - logger.warning("Error reading from clipboard: {}", e) - return None + data = pyclip.paste(text=True) + if not isinstance(data, str): + data = data.decode('utf-8') + logger.debug("Pasted data: {}", data) + return data diff --git a/requirements.txt b/requirements.txt index 46ed9241b..04964d842 100644 --- a/requirements.txt +++ b/requirements.txt @@ -13,3 +13,4 @@ beautifulsoup4==4.12.2 pyyaml==6.0.1 python-jose==3.3.0 requests-cache==1.1.1 +pyclip >= 0.7.0