CtrlCore: Gtk: Added support for pasting/droping Files (RM #401)

git-svn-id: svn://ultimatepp.org/upp/trunk@5698 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2013-01-02 22:00:43 +00:00
parent 11e17eacdd
commit 2594709c17
7 changed files with 84 additions and 34 deletions

View file

@ -131,7 +131,8 @@ public:
~ImageGdk();
};
Image ImageFromPixbufUnref(GdkPixbuf *pixbuf);
String FilesClipFromUrisFree(gchar **uris);
String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf);
GdkAtom GAtom(const String& id);

View file

@ -89,6 +89,7 @@ String Ctrl::GtkDataGet(GtkSelectionData *s)
String Ctrl::Gclipboard::Get(const String& fmt)
{
LLOG("Ctrl::Gclipboard::Get " << fmt);
if(fmt == "text") {
gchar *s = gtk_clipboard_wait_for_text(clipboard);
if(s) {
@ -99,16 +100,19 @@ String Ctrl::Gclipboard::Get(const String& fmt)
return Null;
}
else
if(fmt == "image") {
Image img = ImageFromPixbufUnref(gtk_clipboard_wait_for_image(clipboard));
return StoreAsString(img); // Not very optimal...
}
if(fmt == "image")
return ImageClipFromPixbufUnref(gtk_clipboard_wait_for_image(clipboard));
else
if(fmt == "files")
return FilesClipFromUrisFree(gtk_clipboard_wait_for_uris(clipboard));
else
return GtkDataGet(gtk_clipboard_wait_for_contents(clipboard, GAtom(fmt)));
}
bool Ctrl::Gclipboard::IsAvailable(const String& fmt)
{
if(fmt == "files")
return gtk_clipboard_wait_is_uris_available(clipboard);
if(fmt == "text")
return gtk_clipboard_wait_is_text_available(clipboard);
if(fmt == "image")
@ -336,12 +340,20 @@ bool IsAvailableFiles(PasteClip& clip)
return clip.IsAvailable("files");
}
// TODO:
Vector<String> GetClipFiles(const String& data)
{
Vector<String> r;
Vector<String> f = Split(data, '\n');
for(int i = 0; i < f.GetCount(); i++)
if(f[i].StartsWith("file://"))
r.Add(f[i].Mid(7));
return r;
}
Vector<String> GetFiles(PasteClip& clip)
{
GuiLock __;
Vector<String> f;
return f;
return GetClipFiles(clip.Get("files"));
}
Ptr<Ctrl> Ctrl::sel_ctrl;

View file

@ -90,6 +90,7 @@
static Index<String> dnd_targets;
static String dnd_text_target;
static String dnd_image_target;
static String dnd_files_target;
static String dnd_data;
static String dnd_data_fmt;
static bool dnd_data_wait;

View file

@ -132,6 +132,7 @@ int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
Index<String> Ctrl::dnd_targets;
String Ctrl::dnd_text_target;
String Ctrl::dnd_image_target;
String Ctrl::dnd_files_target;
GtkWidget *Ctrl::dnd_widget;
GdkDragContext *Ctrl::dnd_context;
guint Ctrl::dnd_time;
@ -161,13 +162,17 @@ void Ctrl::DndTargets(GdkDragContext *context)
{
static Index<String> text_targets;
static Index<String> image_targets;
static Index<String> files_targets;
ONCELOCK {
GtkTargetList *target_list = gtk_target_list_new (NULL, 0);
gtk_target_list_add_text_targets (target_list, 0);
gtk_target_list_add_text_targets(target_list, 0);
ToIndex(target_list, text_targets);
GtkTargetList *target_list2 = gtk_target_list_new (NULL, 0);
gtk_target_list_add_image_targets (target_list2, 0, TRUE);
gtk_target_list_add_image_targets(target_list2, 0, TRUE);
ToIndex(target_list2, image_targets);
GtkTargetList *target_list3 = gtk_target_list_new (NULL, 0);
gtk_target_list_add_uri_targets(target_list3, 0);
ToIndex(target_list3, files_targets);
}
dnd_targets.Clear();
dnd_text_target.Clear();
@ -184,6 +189,12 @@ void Ctrl::DndTargets(GdkDragContext *context)
if(dnd_image_target.IsEmpty())
dnd_image_target = g;
}
else
if(files_targets.Find(g) >= 0) {
dnd_targets.Add("files");
if(dnd_files_target.IsEmpty())
dnd_files_target = g;
}
else
dnd_targets.Add(g);
}
@ -193,7 +204,7 @@ void Ctrl::GtkDragDataReceived(GtkWidget *widget, GdkDragContext *context,
gint x, gint y, GtkSelectionData *data,
guint info, guint time, gpointer user_data)
{
LLOG("GtkDragDataReceived");
LLOG("GtkDragDataReceived " << dnd_data_fmt);
dnd_data_wait = false;
if(dnd_data_fmt == "text") {
guchar *s = gtk_selection_data_get_text(data);
@ -203,10 +214,11 @@ void Ctrl::GtkDragDataReceived(GtkWidget *widget, GdkDragContext *context,
}
}
else
if(dnd_data_fmt == "image") {
Image img = ImageFromPixbufUnref(gtk_selection_data_get_pixbuf(data));
dnd_data = StoreAsString(img); // Not very optimal...
}
if(dnd_data_fmt == "image")
dnd_data = ImageClipFromPixbufUnref(gtk_selection_data_get_pixbuf(data));
else
if(dnd_data_fmt == "files")
dnd_data = FilesClipFromUrisFree(gtk_selection_data_get_uris(data));
else
dnd_data = GtkDataGet(data);
}
@ -227,9 +239,9 @@ String Ctrl::DragGet(const char *fmt)
dnd_data_fmt = fmt;
int t0 = msecs();
gtk_drag_get_data(dnd_widget, dnd_context,
GAtom(strcmp(fmt, "image") == 0 ? ~dnd_image_target
: strcmp(fmt, "text") == 0 ? ~dnd_text_target
: fmt),
GAtom(strcmp(fmt, "image") == 0 ? ~dnd_image_target :
strcmp(fmt, "text") == 0 ? ~dnd_text_target :
strcmp(fmt, "files") == 0 ? ~dnd_files_target : fmt),
dnd_time);
while(msecs() - t0 < 1000 && dnd_data_wait)
FetchEvents(true);

View file

@ -9,7 +9,7 @@
NAMESPACE_UPP
#define LLOG(x) // DLOG(x)
#define LOG_EVENTS
//#define LOG_EVENTS _DBG_
bool Ctrl::EventMouseValid;
Point Ctrl::EventMousePos;
@ -368,6 +368,7 @@ void Ctrl::Proc()
w->WhenClose();
}
}
return;
}
case GDK_FOCUS_CHANGE:
LLOG("FocusChange in: " << (bool)CurrentEvent.value << ", focusCtrlWnd " << focusCtrlWnd);

View file

@ -197,6 +197,7 @@ bool TopWindow::IsTopMost() const
void TopWindow::GuiPlatformConstruct()
{
topmost = false;
}
void TopWindow::GuiPlatformDestruct()

View file

@ -98,14 +98,15 @@ GdkRect::GdkRect(const Rect& r)
height = r.GetHeight();
}
Image ImageFromPixbufUnref(GdkPixbuf *pixbuf)
String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf)
{
Image img;
if(pixbuf) {
if(gdk_pixbuf_get_n_channels (pixbuf) == 4 &&
gdk_pixbuf_get_colorspace (pixbuf) == GDK_COLORSPACE_RGB &&
gdk_pixbuf_get_bits_per_sample (pixbuf) == 8 &&
gdk_pixbuf_get_has_alpha (pixbuf)) {
int chn = gdk_pixbuf_get_n_channels(pixbuf);
if((chn == 3 && !gdk_pixbuf_get_has_alpha(pixbuf) ||
chn == 4 && gdk_pixbuf_get_has_alpha(pixbuf)) &&
gdk_pixbuf_get_colorspace(pixbuf) == GDK_COLORSPACE_RGB &&
gdk_pixbuf_get_bits_per_sample(pixbuf) == 8) {
Size sz(gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height(pixbuf));
ImageBuffer m(sz);
int stride = gdk_pixbuf_get_rowstride(pixbuf);
@ -114,6 +115,7 @@ Image ImageFromPixbufUnref(GdkPixbuf *pixbuf)
RGBA *s = m[y];
const RGBA *e = s + sz.cx;
const byte *t = l;
if(chn == 4)
while(s < e) {
s->r = *t++;
s->g = *t++;
@ -121,13 +123,33 @@ Image ImageFromPixbufUnref(GdkPixbuf *pixbuf)
s->a = *t++;
s++;
}
else
while(s < e) {
s->r = *t++;
s->g = *t++;
s->b = *t++;
s->a = 255;
s++;
}
l += stride;
}
img = m;
}
g_object_unref(pixbuf);
}
return img;
return StoreAsString(img);
}
String FilesClipFromUrisFree(gchar **uris)
{
if(uris) {
String h;
for(int i = 0; uris[i]; i++)
h << uris[i] << '\n';
g_strfreev (uris);
return h;
}
return Null;
}
GdkAtom GAtom(const String& id)