From 2594709c17533f228f60687714bc09aed96ac7fb Mon Sep 17 00:00:00 2001 From: cxl Date: Wed, 2 Jan 2013 22:00:43 +0000 Subject: [PATCH] CtrlCore: Gtk: Added support for pasting/droping Files (RM #401) git-svn-id: svn://ultimatepp.org/upp/trunk@5698 f0d560ea-af0d-0410-9eb7-867de7ffcac7 --- uppsrc/CtrlCore/Gtk.h | 3 ++- uppsrc/CtrlCore/GtkClip.cpp | 28 +++++++++++++++------ uppsrc/CtrlCore/GtkCtrl.h | 1 + uppsrc/CtrlCore/GtkDnD.cpp | 34 ++++++++++++++++--------- uppsrc/CtrlCore/GtkEvent.cpp | 3 ++- uppsrc/CtrlCore/GtkTop.cpp | 1 + uppsrc/CtrlCore/GtkUtil.cpp | 48 ++++++++++++++++++++++++++---------- 7 files changed, 84 insertions(+), 34 deletions(-) diff --git a/uppsrc/CtrlCore/Gtk.h b/uppsrc/CtrlCore/Gtk.h index efcb3f280..8be9b9f03 100644 --- a/uppsrc/CtrlCore/Gtk.h +++ b/uppsrc/CtrlCore/Gtk.h @@ -131,7 +131,8 @@ public: ~ImageGdk(); }; -Image ImageFromPixbufUnref(GdkPixbuf *pixbuf); +String FilesClipFromUrisFree(gchar **uris); +String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf); GdkAtom GAtom(const String& id); diff --git a/uppsrc/CtrlCore/GtkClip.cpp b/uppsrc/CtrlCore/GtkClip.cpp index 6ca697d0f..25974433d 100644 --- a/uppsrc/CtrlCore/GtkClip.cpp +++ b/uppsrc/CtrlCore/GtkClip.cpp @@ -73,7 +73,7 @@ void Ctrl::Gclipboard::Put(const String& fmt, const ClipData& data) gtk_clipboard_set_with_data(clipboard, targets, n, GtkGetClipData, ClearClipData, this); gtk_clipboard_set_can_store(clipboard, NULL, 0); - + gtk_target_table_free(targets, n); gtk_target_list_unref(list); } @@ -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 GetClipFiles(const String& data) +{ + Vector r; + Vector 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 GetFiles(PasteClip& clip) { GuiLock __; - Vector f; - return f; + return GetClipFiles(clip.Get("files")); } Ptr Ctrl::sel_ctrl; diff --git a/uppsrc/CtrlCore/GtkCtrl.h b/uppsrc/CtrlCore/GtkCtrl.h index 4055e751d..501b7a2ec 100644 --- a/uppsrc/CtrlCore/GtkCtrl.h +++ b/uppsrc/CtrlCore/GtkCtrl.h @@ -90,6 +90,7 @@ static Index 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; diff --git a/uppsrc/CtrlCore/GtkDnD.cpp b/uppsrc/CtrlCore/GtkDnD.cpp index 1ba6bc063..4ab9721b0 100644 --- a/uppsrc/CtrlCore/GtkDnD.cpp +++ b/uppsrc/CtrlCore/GtkDnD.cpp @@ -4,7 +4,7 @@ NAMESPACE_UPP -#define LLOG(x) // DLOG(x) +#define LLOG(x) // DLOG(x) // -------------------------------------------------------------------------------------------- @@ -132,6 +132,7 @@ int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions, Index 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 text_targets; static Index image_targets; + static Index 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); diff --git a/uppsrc/CtrlCore/GtkEvent.cpp b/uppsrc/CtrlCore/GtkEvent.cpp index d302eb508..8abe13161 100644 --- a/uppsrc/CtrlCore/GtkEvent.cpp +++ b/uppsrc/CtrlCore/GtkEvent.cpp @@ -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); diff --git a/uppsrc/CtrlCore/GtkTop.cpp b/uppsrc/CtrlCore/GtkTop.cpp index f58055159..e2130b0a4 100644 --- a/uppsrc/CtrlCore/GtkTop.cpp +++ b/uppsrc/CtrlCore/GtkTop.cpp @@ -197,6 +197,7 @@ bool TopWindow::IsTopMost() const void TopWindow::GuiPlatformConstruct() { + topmost = false; } void TopWindow::GuiPlatformDestruct() diff --git a/uppsrc/CtrlCore/GtkUtil.cpp b/uppsrc/CtrlCore/GtkUtil.cpp index ade3ce56a..0fa12a46c 100644 --- a/uppsrc/CtrlCore/GtkUtil.cpp +++ b/uppsrc/CtrlCore/GtkUtil.cpp @@ -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,20 +115,41 @@ Image ImageFromPixbufUnref(GdkPixbuf *pixbuf) RGBA *s = m[y]; const RGBA *e = s + sz.cx; const byte *t = l; - while(s < e) { - s->r = *t++; - s->g = *t++; - s->b = *t++; - s->a = *t++; - s++; - } + if(chn == 4) + while(s < e) { + s->r = *t++; + s->g = *t++; + s->b = *t++; + 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)