This commit is contained in:
恍兮惚兮 2025-01-08 13:47:46 +08:00
parent 2893abdb29
commit 646fcc26c3
21 changed files with 145 additions and 106 deletions

View File

@ -1,7 +1,7 @@
set(VERSION_MAJOR 6)
set(VERSION_MINOR 18)
set(VERSION_PATCH 0)
set(VERSION_PATCH 1)
set(VERSION_REVISION 0)
set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}")
add_library(VERSION_DEF ${CMAKE_CURRENT_LIST_DIR}/version_def.cpp)

View File

@ -2,7 +2,7 @@
project(winsharedutils)
add_library(winsharedutils MODULE webview2_extra.cpp AreoAcrylic.cpp screenshot.cpp ../implsapi.cpp hwnd.cpp globalmessagelistener.cpp theme.cpp version.cpp lnk.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp
add_library(winsharedutils MODULE clipboard.cpp webview2_extra.cpp AreoAcrylic.cpp screenshot.cpp ../implsapi.cpp hwnd.cpp globalmessagelistener.cpp theme.cpp version.cpp lnk.cpp levenshtein.cpp muteprocess.cpp sapi_dll.cpp simplemecab.cpp
applicationloopbackaudio/runer.cpp applicationloopbackaudio/LoopbackCapture.cpp
SimpleBrowser.cpp MWebBrowser.cpp icon.cpp ${versioninfo})
target_precompile_headers(winsharedutils REUSE_FROM pch)

View File

@ -20,9 +20,11 @@ bool tryopenclipboard(HWND hwnd = 0)
std::optional<std::wstring> clipboard_get_internal()
{
std::optional<std::wstring> data = {};
if (!IsClipboardFormatAvailable(CF_UNICODETEXT))
return {};
if (tryopenclipboard() == false)
return {};
std::optional<std::wstring> data = {};
do
{
HANDLE hData = GetClipboardData(CF_UNICODETEXT);
@ -80,7 +82,13 @@ DECLARE_API bool clipboard_set(HWND hwnd, wchar_t *text)
CloseClipboard();
return success;
}
inline bool iscurrentowndclipboard()
{
auto ohwnd = GetClipboardOwner();
DWORD pid;
GetWindowThreadProcessId(ohwnd, &pid);
return pid == GetCurrentProcessId();
}
static void clipboard_callback_1(void (*callback)(const wchar_t *, bool), HANDLE hsema, HWND *hwnd)
{
const wchar_t CLASS_NAME[] = L"LunaClipboardListener";
@ -91,14 +99,12 @@ static void clipboard_callback_1(void (*callback)(const wchar_t *, bool), HANDLE
static auto callbackx = [](HWND hWnd)
{
auto data = clipboard_get_internal();
if (!data)
return;
auto callback_ = reinterpret_cast<decltype(callback)>(GetWindowLongPtrW(hWnd, GWLP_USERDATA));
if (data && callback_)
{
auto ohwnd = GetClipboardOwner();
DWORD pid;
GetWindowThreadProcessId(ohwnd, &pid);
callback_(data.value().c_str(), pid == GetCurrentProcessId());
}
if (!callback_)
return;
callback_(data.value().c_str(), iscurrentowndclipboard());
};
#ifndef WINXP
if (WM_CLIPBOARDUPDATE == message)
@ -158,9 +164,9 @@ static void clipboard_callback_1(void (*callback)(const wchar_t *, bool), HANDLE
DispatchMessage(&msg);
}
}
#ifndef WINXP
DECLARE_API HWND clipboard_callback(void (*callback)(const wchar_t *, bool))
{
#ifndef WINXP
HANDLE hsema = CreateSemaphoreW(0, 0, 10, 0);
HWND hwnd;
@ -172,31 +178,26 @@ DECLARE_API HWND clipboard_callback(void (*callback)(const wchar_t *, bool))
return hwnd;
else
return NULL;
}
#else
static int running = false;
DECLARE_API HWND clipboard_callback(void (*callback)(const wchar_t *, bool))
{
running = true;
std::thread([=]()
static HANDLE clipboardUpdate;
clipboardUpdate = CreateEventW(nullptr, FALSE, TRUE, NULL);
auto __ = SetWindowsHookExW(WH_GETMESSAGE, [](int statusCode, WPARAM wParam, LPARAM lParam)
{
if (statusCode == HC_ACTION && wParam == PM_REMOVE && ((MSG*)lParam)->message == WM_CLIPBOARDUPDATE) SetEvent(clipboardUpdate);
return CallNextHookEx(NULL, statusCode, wParam, lParam); }, NULL, GetCurrentThreadId());
std::thread([=]
{
std::wstring last;
while(running){
Sleep(100);
auto data = clipboard_get_internal();
if(data){
if(last==data.value())continue;
last=data.value();
auto ohwnd = GetClipboardOwner();
DWORD pid;
GetWindowThreadProcessId(ohwnd, &pid);
callback(data.value().c_str(), pid == GetCurrentProcessId());
}
} })
while (WaitForSingleObject(clipboardUpdate, INFINITE) == WAIT_OBJECT_0)
{
auto data = clipboard_get_internal();
if(data)
callback(data.value().c_str(), iscurrentowndclipboard());
}
throw; })
.detach();
return NULL;
}
return (HWND) new std::pair<HANDLE, HHOOK>{clipboardUpdate, __};
#endif
}
DECLARE_API void clipboard_callback_stop(HWND hwnd)
{
#ifndef WINXP
@ -205,7 +206,10 @@ DECLARE_API void clipboard_callback_stop(HWND hwnd)
RemoveClipboardFormatListener(hwnd);
DestroyWindow(hwnd);
#else
running = false;
auto __ = (std::pair<HANDLE, HHOOK> *)(hwnd);
UnhookWindowsHookEx(__->second);
CloseHandle(__->first);
delete __;
#endif
}

View File

@ -53,18 +53,6 @@ from gui.dynalang import LAction, LMenu
from gui.setting_textinput_ocr import showocrimage
class _clipboardhelper(QObject):
setText = pyqtSignal(str)
setPixmap = pyqtSignal(QPixmap)
setImage = pyqtSignal(QImage)
def __init__(self):
super().__init__()
self.setPixmap.connect(QApplication.clipboard().setPixmap)
self.setImage.connect(QApplication.clipboard().setImage)
self.setText.connect(QApplication.clipboard().setText)
class MAINUI:
def __init__(self) -> None:
super().__init__()
@ -978,8 +966,8 @@ class MAINUI:
word = word.get("origorig", word["orig"])
if globalconfig["usecopyword"]:
gobject.baseobject.clipboardhelper.setText.emit(
(QApplication.clipboard().text("plain")[0] + word) if append else word
winsharedutils.clipboard_set(
(winsharedutils.clipboard_get() + word) if append else word
)
if globalconfig["usesearchword"]:
self.searchwordW.search_word.emit(word, append)
@ -1156,7 +1144,6 @@ class MAINUI:
# ).family()
def loadui(self):
self.clipboardhelper = _clipboardhelper()
self.installeventfillter()
self.parsedefaultfont()
self.loadmetadatas()

View File

@ -2,8 +2,8 @@ from qtsymbols import *
import functools, uuid
from datetime import datetime, timedelta
from traceback import print_exc
import gobject
from language import TransLanguages
import gobject, winsharedutils
from myutils.config import (
savehook_new_data,
uid2gamepath,
@ -631,7 +631,7 @@ class dialog_setting_game_internal(QWidget):
try:
gobject.global_dialog_savedgame_new.tagswidget.addTag(*_)
except:
gobject.baseobject.clipboardhelper.setText.emit(_[0])
winsharedutils.clipboard_set(_[0])
qw.labelclicked.connect(safeaddtags)
if first:

View File

@ -10,6 +10,7 @@ from myutils.config import (
extradatas,
globalconfig,
)
from myutils.hwnd import clipboard_set_image
from myutils.utils import (
get_time_stamp,
loopbackrecorder,
@ -572,9 +573,7 @@ class pixwrapper(QWidget):
if action == deleteimage:
self.removecurrent(False)
elif copyimage == action:
gobject.baseobject.clipboardhelper.setImage.emit(
QImage(extradatas["localedpath"].get(curr, curr))
)
clipboard_set_image(extradatas["localedpath"].get(curr, curr))
elif action == deleteimage_x:
self.removecurrent(True)
elif action == pos:

View File

@ -2,7 +2,7 @@ from qtsymbols import *
import functools, binascii
from collections import OrderedDict
from traceback import print_exc
import qtawesome, windows, gobject
import qtawesome, windows, winsharedutils, gobject
from textsource.texthook import codepage_display, codepage_real
from myutils.config import savehook_new_data, static_data, globalconfig, _TR, isascii
from myutils.utils import checkchaos, get_time_stamp, dynamiclink, is_ascii_control
@ -693,7 +693,7 @@ class hookselect(closeashidewindow):
except:
pass
elif action == copy:
gobject.baseobject.clipboardhelper.setText.emit(hc)
winsharedutils.clipboard_set(hc)
def opensolvetext(self):
try:

View File

@ -49,9 +49,7 @@ def registrhotkeys(self):
"_1": gobject.baseobject.translation_ui.startTranslater,
"_2": gobject.baseobject.translation_ui.changeTranslateMode,
"_3": self.showsignal.emit,
"_4": lambda: gobject.baseobject.clipboardhelper.setText.emit(
gobject.baseobject.currenttext
),
"_4": lambda: winsharedutils.clipboard_set(gobject.baseobject.currenttext),
"_5": gobject.baseobject.translation_ui.changeshowhiderawsig.emit,
"_51": gobject.baseobject.translation_ui.changeshowhidetranssig.emit,
"_6": lambda: gobject.baseobject.transhis.showsignal.emit(),
@ -75,15 +73,13 @@ def registrhotkeys(self):
"_25": lambda: windows.SendMessage(
windows.FindWindow("WNDCLS_Magpie_Core_CLI_Message", None),
windows.RegisterWindowMessage("Magpie_Core_CLI_Message_ToggleOverlay"),
None,
None,
),
"_26": gobject.baseobject.translation_ui.ocr_once_signal.emit,
"_26_1": lambda: gobject.baseobject.translation_ui.ocr_do_function(
gobject.baseobject.translation_ui.ocr_once_follow_rect
),
"_27": gobject.baseobject.translation_ui.simulate_key_enter,
"_28": lambda: gobject.baseobject.clipboardhelper.setText.emit(
"_28": lambda: winsharedutils.clipboard_set(
gobject.baseobject.currenttranslate
),
"_29": lambda: gobject.baseobject.searchwordW.ankiwindow.recordbtn1.click(),
@ -95,7 +91,7 @@ def registrhotkeys(self):
QPoint()
),
"36": lambda: gobject.baseobject.textgetmethod(
QApplication.clipboard().text("plain")[0], False
winsharedutils.clipboard_get(), False
),
"37": lambda: gobject.baseobject.searchwordW.search_word.emit(
winsharedutils.GetSelectedText(), False

View File

@ -2,7 +2,7 @@ from qtsymbols import *
import json, time, functools, os, base64, uuid
from urllib.parse import quote
from traceback import print_exc
import qtawesome, requests, gobject, windows, hashlib
import qtawesome, requests, gobject, windows, winsharedutils
import myutils.ankiconnect as anki
from myutils.hwnd import grabwindow
from myutils.config import globalconfig, static_data, _TR
@ -971,7 +971,7 @@ class showdiction(QWidget):
if action == search:
self.model.onDoubleClicked(idx)
elif copy == action:
gobject.baseobject.clipboardhelper.setText.emit(item.text())
winsharedutils.clipboard_set(item.text())
elif action == label:
if not idx.data(isLabeleddWord):
item.setData(True, isLabeleddWord)

View File

@ -1,6 +1,6 @@
from qtsymbols import *
import functools
import qtawesome, gobject, threading
import qtawesome, winsharedutils, threading
from myutils.config import globalconfig
from myutils.utils import get_time_stamp
from gui.usefulwidget import closeashidewindow
@ -70,7 +70,7 @@ class transhist(closeashidewindow):
if action == qingkong:
tb.clear()
elif action == copy:
gobject.baseobject.clipboardhelper.setText.emit(self.textOutput.textCursor().selectedText())
winsharedutils.clipboard_set(self.textOutput.textCursor().selectedText())
elif action == baocun:
ff = QFileDialog.getSaveFileName(self, directory="save.txt")
if ff[0] == "":

View File

@ -566,7 +566,7 @@ class TranslatorWindow(resizableframeless):
("setting", lambda: gobject.baseobject.settin_ui.showsignal.emit()),
(
"copy",
lambda: gobject.baseobject.clipboardhelper.setText.emit(gobject.baseobject.currenttext),
lambda: winsharedutils.clipboard_set(gobject.baseobject.currenttext),
),
("edit", gobject.baseobject.createedittextui),
("edittrans", lambda: edittrans(gobject.baseobject.commonstylebase)),
@ -700,7 +700,7 @@ class TranslatorWindow(resizableframeless):
(
"copy_once",
lambda: gobject.baseobject.textgetmethod(
QApplication.clipboard().text("plain")[0], False
winsharedutils.clipboard_get(), False
),
),
(

View File

@ -318,13 +318,13 @@ class TableViewW(QTableView):
csv_writer.writerow(row)
csv_str = output.getvalue()
output.close()
gobject.baseobject.clipboardhelper.setText.emit(csv_str)
winsharedutils.clipboard_set(csv_str)
def pastetable(self):
current = self.currentIndex()
if not current.isValid():
return
string = QApplication.clipboard().text("plain")[0]
string = winsharedutils.clipboard_get()
try:
csv_file = io.StringIO(string)
csv_reader = csv.reader(csv_file, delimiter="\t")
@ -1443,7 +1443,7 @@ class mshtmlWidget(abstractwebview):
t.timeout.connect(self.__getcurrent)
t.timeout.emit()
t.start()
self.add_menu(0, _TR("复制"), gobject.baseobject.clipboardhelper.setText.emit)
self.add_menu(0, _TR("复制"), winsharedutils.clipboard_set)
self.add_menu(0, None, lambda: 1)
def __getcurrent(self):
@ -1456,9 +1456,7 @@ class mshtmlWidget(abstractwebview):
winsharedutils.html_get_current_url(self.browser, cb)
if winsharedutils.html_check_ctrlc(self.browser):
cb = winsharedutils.html_get_select_text_cb(
gobject.baseobject.clipboardhelper.setText.emit
)
cb = winsharedutils.html_get_select_text_cb(winsharedutils.clipboard_set)
winsharedutils.html_get_select_text(self.browser, cb)
def navigate(self, url):
@ -1960,9 +1958,7 @@ class listediter(LDialog):
self.hcmodel.removeRow(curr.row())
self.internalrealname.pop(curr.row())
elif action == copy:
gobject.baseobject.clipboardhelper.setText.emit(
self.hcmodel.itemFromIndex(curr).text()
)
winsharedutils.clipboard_set(self.hcmodel.itemFromIndex(curr).text())
elif action == up:

View File

@ -6,6 +6,19 @@ import os, subprocess, functools
import time, winrtutils, winsharedutils, hashlib
from myutils.config import savehook_new_data, globalconfig
from myutils.wrapper import threader
from myutils.utils import qimage2binary
def clipboard_set_image(p: QImage):
if not p:
return
if isinstance(p, str):
qimg = QImage()
qimg.load(p)
p = qimg
if p.isNull():
return
winsharedutils.clipboard_set_image(qimage2binary(p))
@threader
@ -46,7 +59,7 @@ def grabwindow(app="PNG", callback_origin=None, tocliponly=False):
if p.isNull():
return
if tocliponly:
gobject.baseobject.clipboardhelper.setPixmap.emit(p)
clipboard_set_image(p)
return
p.save(fn)
if callback_origin:

View File

@ -1,7 +1,7 @@
from qtsymbols import *
from myutils.config import globalconfig, static_data
from rendertext.somefunctions import dataget
import gobject, functools, importlib
import gobject, functools, importlib, winsharedutils
from traceback import print_exc
from rendertext.textbrowser_imp.base import base
from gui.dynalang import LAction
@ -175,7 +175,7 @@ class TextBrowser(QWidget, dataget):
if action == search:
gobject.baseobject.searchwordW.search_word.emit(curr, False)
elif action == copy:
gobject.baseobject.clipboardhelper.setText.emit(curr)
winsharedutils.clipboard_set(curr)
elif action == tts:
gobject.baseobject.read_text(curr)
elif action == translate:

View File

@ -37,8 +37,6 @@ class Method(scalebase):
windows.SendMessage(
windows.FindWindow("WNDCLS_Magpie_Core_CLI_Message", None),
windows.RegisterWindowMessage("Magpie_Core_CLI_Message_Exit"),
None,
None,
)
def changestatus(self, hwnd, full):
@ -58,7 +56,5 @@ class Method(scalebase):
windows.SendMessage(
windows.FindWindow("WNDCLS_Magpie_Core_CLI_Message", None),
windows.RegisterWindowMessage("Magpie_Core_CLI_Message_Stop"),
None,
None,
)
return False

View File

@ -1,7 +1,6 @@
from textoutput.outputerbase import Base
from myutils.config import globalconfig
import gobject
from qtsymbols import *
import winsharedutils
class Outputer(Base):
@ -10,4 +9,5 @@ class Outputer(Base):
not globalconfig["excule_from_self"]
):
return
gobject.baseobject.clipboardhelper.setText.emit(text)
winsharedutils.clipboard_set(text)

View File

@ -1,23 +1,22 @@
from textsource.textsourcebase import basetext
from myutils.config import globalconfig
import gobject
from qtsymbols import *
import winsharedutils, gobject
class copyboard(basetext):
def end(self):
QApplication.clipboard().disconnect()
winsharedutils.clipboard_callback_stop(self.__hwnd)
def __callback(self):
clipboard = QApplication.clipboard()
if globalconfig["excule_from_self"] and clipboard.ownsClipboard():
def __callback(self, string, ismy):
if globalconfig["excule_from_self"] and ismy:
return
self.dispatchtext(clipboard.text("plain")[0])
self.dispatchtext(string)
def init(self) -> None:
self.startsql(gobject.gettranslationrecorddir("0_copy.sqlite"))
QApplication.clipboard().dataChanged.connect(self.__callback)
self.__ref = winsharedutils.clipboard_callback_type(self.__callback)
self.__hwnd = winsharedutils.clipboard_callback(self.__ref)
def gettextonce(self):
return QApplication.clipboard().text("plain")[0]
return winsharedutils.clipboard_get()

View File

@ -15,24 +15,27 @@ class TTS(TTSbase):
for modelType in modelTypes:
vits_data = responseVits[modelType]
for item in vits_data:
model_info = "{}_{}_{}".format(modelType, item["id"], item["name"])
lang_str = "/".join(item["lang"])
model_info = "{}_{}_{}_{}".format(
modelType, item["id"], item["name"], lang_str
)
voicelist.append(model_info)
internal.append((modelType, item["id"], item["name"]))
return internal, voicelist
def speak(self, content, voice, param: SpeechParam):
if param.speed > 0:
rate = 1 - param.speed / 15
length = 1 - param.speed / 15
else:
rate = 1 - param.speed / 5
length = 1 - param.speed / 5
encoded_content = quote(content)
model, idx, _ = voice
speak = self.config["speak"].format(
speak = self.config["speak2"].format(
model_lower=model.lower(),
model=model,
id=idx,
text=encoded_content,
speed=rate,
length=length,
)
response = requests.get(urlpathjoin(self.config["URL"], speak)).content

View File

@ -272,8 +272,8 @@ _OpenProcess.argtypes = c_uint, c_bool, c_uint
CloseHandle = _kernel32.CloseHandle
CloseHandle.argtypes = (HANDLE,)
CloseHandle.restype = BOOL
SendMessage = _user32.SendMessageW
SendMessage.argtypes = c_int, c_uint, c_void_p, c_void_p
_SendMessage = _user32.SendMessageW
_SendMessage.argtypes = c_int, c_uint, c_void_p, c_void_p
_keybd_event = _user32.keybd_event
_keybd_event.argtypes = c_byte, c_byte, c_uint, c_void_p
RegisterWindowMessage = _user32.RegisterWindowMessageW
@ -281,6 +281,8 @@ RegisterWindowMessage.argtypes = (LPCWSTR,)
RegisterWindowMessage.restype = UINT
_GetWindowThreadProcessId = _user32.GetWindowThreadProcessId
_GetWindowThreadProcessId.argtypes = HWND, c_void_p
GetClipboardOwner = _user32.GetClipboardOwner
GetClipboardOwner.restype = HWND
try:
_GetModuleFileNameExW = _psapi.GetModuleFileNameExW
except:
@ -497,6 +499,10 @@ def OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId):
return _OpenProcess(dwDesiredAccess, bInheritHandle, dwProcessId)
def SendMessage(hwnd, message, wp=None, lp=None):
return _SendMessage(hwnd, message, wp, lp)
def keybd_event(bVk, bScan, dwFlags, _):
_keybd_event(bVk, bScan, dwFlags, _)

View File

@ -54,6 +54,15 @@ mecab_parse.restype = c_bool
mecab_end = utilsdll.mecab_end
mecab_end.argtypes = (c_void_p,)
_clipboard_get = utilsdll.clipboard_get
_clipboard_get.argtypes = (c_void_p,)
_clipboard_get.restype = c_bool
_clipboard_set = utilsdll.clipboard_set
_clipboard_set.argtypes = (HWND, c_wchar_p)
_clipboard_set_image = utilsdll.clipboard_set_image
_clipboard_set_image.argtypes = (HWND, c_void_p, c_size_t)
_clipboard_set_image.restype = c_bool
def SAPI_List(v):
ret = []
@ -83,6 +92,26 @@ def distance_ratio(s1, s2):
return levenshtein_ratio(len(s1), s1, len(s2), s2)
clphwnd = windll.user32.CreateWindowExW(0, "STATIC", 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
def clipboard_set(text):
global clphwnd
return _clipboard_set(clphwnd, text)
def clipboard_set_image(bytes_):
global clphwnd
return _clipboard_set_image(clphwnd, bytes_, len(bytes_))
def clipboard_get():
ret = []
if not _clipboard_get(CFUNCTYPE(None, c_wchar_p)(ret.append)):
return ""
return ret[0]
html_version = utilsdll.html_version
html_version.restype = DWORD
html_new = utilsdll.html_new
@ -288,6 +317,12 @@ add_menu_list = utilsdll.add_menu_list
add_menu_list.argtypes = (c_void_p, c_int, c_wchar_p, add_ContextMenuRequested_cb)
get_root_html = utilsdll.get_root_html
get_root_html.argtypes = c_void_p, c_void_p
clipboard_callback = utilsdll.clipboard_callback
clipboard_callback.argtypes = (c_void_p,)
clipboard_callback.restype = HWND
clipboard_callback_stop = utilsdll.clipboard_callback_stop
clipboard_callback_stop.argtypes = (HWND,)
clipboard_callback_type = CFUNCTYPE(None, c_wchar_p, c_bool)
StartCaptureAsync_cb = CFUNCTYPE(None, c_void_p, c_size_t)
StartCaptureAsync = utilsdll.StartCaptureAsync
StartCaptureAsync.argtypes = (StartCaptureAsync_cb,)

View File

@ -1182,7 +1182,12 @@
"args": {
"URL": "http://127.0.0.1:23456",
"voices": "/voice/speakers",
"speak": "/voice/{model_lower}?text={text}&id={id}&length={speed}&lang=auto&prompt_lang=auto&format=wav&preset=default"
"speak2": "/voice/{model_lower}?text={text}&id={id}&length={length}&lang=auto&prompt_lang=auto&format=wav&preset=default"
},
"argstype": {
"speak2": {
"name": "speak"
}
},
"arg_not_sup": [
"pitch"