mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 06:05:58 -06:00
CtrlCore: X11 Optimized clipboard handling
This commit is contained in:
parent
f07e8ae05c
commit
32a6d9eb56
8 changed files with 66 additions and 27 deletions
10
benchmarks/IsClipboardText/IsClipboardText.upp
Normal file
10
benchmarks/IsClipboardText/IsClipboardText.upp
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
uses
|
||||
CtrlLib;
|
||||
|
||||
file
|
||||
main.cpp;
|
||||
|
||||
mainconfig
|
||||
"" = "GUI",
|
||||
"" = "GUI X11";
|
||||
|
||||
24
benchmarks/IsClipboardText/main.cpp
Normal file
24
benchmarks/IsClipboardText/main.cpp
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#include <CtrlLib/CtrlLib.h>
|
||||
|
||||
using namespace Upp;
|
||||
|
||||
struct MyApp : TopWindow {
|
||||
void Paint(Draw& w) override {
|
||||
w.DrawRect(GetSize(), White());
|
||||
for(int i = 0; i < 100; i++) {
|
||||
{
|
||||
RTIMING("IsClipboardAvailableText");
|
||||
IsClipboardAvailableText();
|
||||
}
|
||||
{
|
||||
RTIMING("IsClipboardAvailableImage");
|
||||
IsClipboardAvailableImage();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
GUI_APP_MAIN
|
||||
{
|
||||
MyApp().Run();
|
||||
}
|
||||
|
|
@ -157,7 +157,6 @@ INITBLOCK {
|
|||
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
|
||||
Color ink, int n, const int *dx) {
|
||||
GuiLock __;
|
||||
DTIMING("DrawText");
|
||||
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
|
||||
//TODO - X11 seems to crash when displaying too long strings (?)
|
||||
int ox = x + actual_offset.x;
|
||||
|
|
|
|||
|
|
@ -152,7 +152,6 @@ static XPicture sGetSolidFill(Color c)
|
|||
void ImageSysData::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
||||
{
|
||||
GuiLock __;
|
||||
DTIMING("PAINT IMAGE");
|
||||
x += w.GetOffset().x;
|
||||
y += w.GetOffset().y;
|
||||
Size sz = img.GetSize();
|
||||
|
|
|
|||
|
|
@ -142,6 +142,23 @@ String Ctrl::Xclipboard::Read(int fmt, int selection, int property)
|
|||
return Null;
|
||||
}
|
||||
|
||||
bool Ctrl::Xclipboard::IsAvailable(int fmt, bool primary)
|
||||
{
|
||||
GuiLock __;
|
||||
if(data.GetCount())
|
||||
return data.Find(fmt) >= 0;
|
||||
String& formats = this->formats[primary];
|
||||
if(formats.IsVoid())
|
||||
formats = Read(XAtom("TARGETS"), XAtom(primary ? "PRIMARY" : "CLIPBOARD"), XAtom("CLIPDATA"));
|
||||
int c = formats.GetCount() / sizeof(Atom);
|
||||
const Atom *m = (Atom *) ~formats;
|
||||
for(int i = 0; i < c; i++) {
|
||||
if(m[i] == (dword)fmt)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Ctrl::Xclipboard& Ctrl::xclipboard()
|
||||
{
|
||||
static Xclipboard xc;
|
||||
|
|
@ -200,21 +217,6 @@ WString ReadClipboardUnicodeText()
|
|||
return ToUtf32(ReadClipboard("UTF8_STRING"));
|
||||
}
|
||||
|
||||
bool Ctrl::Xclipboard::IsAvailable(int fmt, const char *type)
|
||||
{
|
||||
GuiLock __;
|
||||
if(data.GetCount())
|
||||
return data.Find(fmt) >= 0;
|
||||
String formats = Read(XAtom("TARGETS"), XAtom(type), XAtom("CLIPDATA"));
|
||||
int c = formats.GetCount() / sizeof(Atom);
|
||||
const Atom *m = (Atom *) ~formats;
|
||||
for(int i = 0; i < c; i++) {
|
||||
if(m[i] == (dword)fmt)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Ctrl::ClipHas(int type, const char *fmt)
|
||||
{
|
||||
GuiLock __;
|
||||
|
|
@ -222,11 +224,11 @@ bool Ctrl::ClipHas(int type, const char *fmt)
|
|||
if(strcmp(fmt, "files") == 0)
|
||||
fmt = "text/uri-list";
|
||||
if(type == 0)
|
||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), "CLIPBOARD");
|
||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), false);
|
||||
if(type == 2) {
|
||||
if(sel_ctrl)
|
||||
return sel_formats.Find(fmt) >= 0;
|
||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), "PRIMARY");
|
||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), true);
|
||||
}
|
||||
return drop_formats.Find(fmt) >= 0;
|
||||
}
|
||||
|
|
@ -318,7 +320,7 @@ void Append(VectorMap<String, ClipData>& data, const WString& text) // optimize
|
|||
bool IsClipboardAvailable(const char *fmt)
|
||||
{
|
||||
GuiLock __;
|
||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), "CLIPBOARD");
|
||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), false);
|
||||
}
|
||||
|
||||
bool IsClipboardAvailableText()
|
||||
|
|
|
|||
|
|
@ -69,12 +69,15 @@ public:
|
|||
Window win;
|
||||
|
||||
VectorMap<int, ClipData> data;
|
||||
|
||||
String formats[2]; // 0 CLIPBOARD, 1 PRIMARY
|
||||
|
||||
String Read(int fmt, int selection, int property);
|
||||
void Write(int fmt, const ClipData& data);
|
||||
bool IsAvailable(int fmt, const char *type);
|
||||
bool IsAvailable(int fmt, bool primary);
|
||||
|
||||
void Clear() { data.Clear(); }
|
||||
void InvalidateFormats() { formats[0] = String::GetVoid(); formats[1] = String::GetVoid(); }
|
||||
void Clear() { data.Clear(); InvalidateFormats(); }
|
||||
void Request(XSelectionRequestEvent *se);
|
||||
|
||||
Xclipboard();
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ void Ctrl::SetLastActive(XWindow *w, Ctrl *la)
|
|||
|
||||
void Ctrl::EventProc(XWindow& w, XEvent *event)
|
||||
{
|
||||
GuiLock __;
|
||||
GuiLock __;
|
||||
eventid++;
|
||||
Ptr<Ctrl> _this = this;
|
||||
bool pressed = false;
|
||||
|
|
@ -109,10 +109,12 @@ void Ctrl::EventProc(XWindow& w, XEvent *event)
|
|||
LTIMING("XUserInput");
|
||||
switch(event->type) {
|
||||
case FocusIn:
|
||||
xclipboard().InvalidateFormats();
|
||||
if(w.xic)
|
||||
XSetICFocus(w.xic);
|
||||
break;
|
||||
case FocusOut:
|
||||
xclipboard().InvalidateFormats();
|
||||
if(w.xic)
|
||||
XUnsetICFocus(w.xic);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -43,24 +43,24 @@ void TopWindow::EventProc(XWindow& w, XEvent *event)
|
|||
if(event->xclient.message_type == XAtom("WM_PROTOCOLS")) {
|
||||
Atom a = event->xclient.data.l[0];
|
||||
if(a == XAtom("WM_DELETE_WINDOW") && IsEnabled()) {
|
||||
DLOG("DELETE_WINDOW " << Name());
|
||||
LLOG("DELETE_WINDOW " << Name());
|
||||
WhenClose();
|
||||
return;
|
||||
}
|
||||
if(a == XAtom("WM_TAKE_FOCUS")) {
|
||||
DLOG("TAKE_FOCUS serial: " << event->xclient.serial);
|
||||
LLOG("TAKE_FOCUS serial: " << event->xclient.serial);
|
||||
Xeventtime = event->xclient.data.l[1];
|
||||
TakeFocus();
|
||||
return;
|
||||
}
|
||||
if(a == XAtom("_NET_WM_PING")) {
|
||||
DLOG("_NET_WM_PING");
|
||||
LLOG("_NET_WM_PING");
|
||||
XEvent ev = *event;
|
||||
ev.xclient.window = Xroot;
|
||||
XSendEvent(Xdisplay, Xroot, 0, SubstructureRedirectMask|SubstructureNotifyMask, &ev);
|
||||
return;
|
||||
}
|
||||
DLOG("Unknown WM_PROTOCOLS: " << XAtomName(a));
|
||||
LLOG("Unknown WM_PROTOCOLS: " << XAtomName(a));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue