mirror of
https://github.com/ultimatepp/ultimatepp.git
synced 2026-05-15 14:16:07 -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,
|
void SystemDraw::DrawTextOp(int x, int y, int angle, const wchar *text, Font font,
|
||||||
Color ink, int n, const int *dx) {
|
Color ink, int n, const int *dx) {
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
DTIMING("DrawText");
|
|
||||||
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
|
LLOG("DrawText " << ToUtf8(WString(text, n)) << " color:" << ink << " font:" << font);
|
||||||
//TODO - X11 seems to crash when displaying too long strings (?)
|
//TODO - X11 seems to crash when displaying too long strings (?)
|
||||||
int ox = x + actual_offset.x;
|
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)
|
void ImageSysData::Paint(SystemDraw& w, int x, int y, const Rect& src, Color c)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
DTIMING("PAINT IMAGE");
|
|
||||||
x += w.GetOffset().x;
|
x += w.GetOffset().x;
|
||||||
y += w.GetOffset().y;
|
y += w.GetOffset().y;
|
||||||
Size sz = img.GetSize();
|
Size sz = img.GetSize();
|
||||||
|
|
|
||||||
|
|
@ -142,6 +142,23 @@ String Ctrl::Xclipboard::Read(int fmt, int selection, int property)
|
||||||
return Null;
|
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()
|
Ctrl::Xclipboard& Ctrl::xclipboard()
|
||||||
{
|
{
|
||||||
static Xclipboard xc;
|
static Xclipboard xc;
|
||||||
|
|
@ -200,21 +217,6 @@ WString ReadClipboardUnicodeText()
|
||||||
return ToUtf32(ReadClipboard("UTF8_STRING"));
|
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)
|
bool Ctrl::ClipHas(int type, const char *fmt)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
|
|
@ -222,11 +224,11 @@ bool Ctrl::ClipHas(int type, const char *fmt)
|
||||||
if(strcmp(fmt, "files") == 0)
|
if(strcmp(fmt, "files") == 0)
|
||||||
fmt = "text/uri-list";
|
fmt = "text/uri-list";
|
||||||
if(type == 0)
|
if(type == 0)
|
||||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), "CLIPBOARD");
|
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), false);
|
||||||
if(type == 2) {
|
if(type == 2) {
|
||||||
if(sel_ctrl)
|
if(sel_ctrl)
|
||||||
return sel_formats.Find(fmt) >= 0;
|
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;
|
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)
|
bool IsClipboardAvailable(const char *fmt)
|
||||||
{
|
{
|
||||||
GuiLock __;
|
GuiLock __;
|
||||||
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), "CLIPBOARD");
|
return Ctrl::xclipboard().IsAvailable(XAtom(fmt), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsClipboardAvailableText()
|
bool IsClipboardAvailableText()
|
||||||
|
|
|
||||||
|
|
@ -70,11 +70,14 @@ public:
|
||||||
|
|
||||||
VectorMap<int, ClipData> data;
|
VectorMap<int, ClipData> data;
|
||||||
|
|
||||||
|
String formats[2]; // 0 CLIPBOARD, 1 PRIMARY
|
||||||
|
|
||||||
String Read(int fmt, int selection, int property);
|
String Read(int fmt, int selection, int property);
|
||||||
void Write(int fmt, const ClipData& data);
|
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);
|
void Request(XSelectionRequestEvent *se);
|
||||||
|
|
||||||
Xclipboard();
|
Xclipboard();
|
||||||
|
|
|
||||||
|
|
@ -109,10 +109,12 @@ void Ctrl::EventProc(XWindow& w, XEvent *event)
|
||||||
LTIMING("XUserInput");
|
LTIMING("XUserInput");
|
||||||
switch(event->type) {
|
switch(event->type) {
|
||||||
case FocusIn:
|
case FocusIn:
|
||||||
|
xclipboard().InvalidateFormats();
|
||||||
if(w.xic)
|
if(w.xic)
|
||||||
XSetICFocus(w.xic);
|
XSetICFocus(w.xic);
|
||||||
break;
|
break;
|
||||||
case FocusOut:
|
case FocusOut:
|
||||||
|
xclipboard().InvalidateFormats();
|
||||||
if(w.xic)
|
if(w.xic)
|
||||||
XUnsetICFocus(w.xic);
|
XUnsetICFocus(w.xic);
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -43,24 +43,24 @@ void TopWindow::EventProc(XWindow& w, XEvent *event)
|
||||||
if(event->xclient.message_type == XAtom("WM_PROTOCOLS")) {
|
if(event->xclient.message_type == XAtom("WM_PROTOCOLS")) {
|
||||||
Atom a = event->xclient.data.l[0];
|
Atom a = event->xclient.data.l[0];
|
||||||
if(a == XAtom("WM_DELETE_WINDOW") && IsEnabled()) {
|
if(a == XAtom("WM_DELETE_WINDOW") && IsEnabled()) {
|
||||||
DLOG("DELETE_WINDOW " << Name());
|
LLOG("DELETE_WINDOW " << Name());
|
||||||
WhenClose();
|
WhenClose();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(a == XAtom("WM_TAKE_FOCUS")) {
|
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];
|
Xeventtime = event->xclient.data.l[1];
|
||||||
TakeFocus();
|
TakeFocus();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if(a == XAtom("_NET_WM_PING")) {
|
if(a == XAtom("_NET_WM_PING")) {
|
||||||
DLOG("_NET_WM_PING");
|
LLOG("_NET_WM_PING");
|
||||||
XEvent ev = *event;
|
XEvent ev = *event;
|
||||||
ev.xclient.window = Xroot;
|
ev.xclient.window = Xroot;
|
||||||
XSendEvent(Xdisplay, Xroot, 0, SubstructureRedirectMask|SubstructureNotifyMask, &ev);
|
XSendEvent(Xdisplay, Xroot, 0, SubstructureRedirectMask|SubstructureNotifyMask, &ev);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
DLOG("Unknown WM_PROTOCOLS: " << XAtomName(a));
|
LLOG("Unknown WM_PROTOCOLS: " << XAtomName(a));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue