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(); ~ImageGdk();
}; };
Image ImageFromPixbufUnref(GdkPixbuf *pixbuf); String FilesClipFromUrisFree(gchar **uris);
String ImageClipFromPixbufUnref(GdkPixbuf *pixbuf);
GdkAtom GAtom(const String& id); GdkAtom GAtom(const String& id);

View file

@ -89,6 +89,7 @@ String Ctrl::GtkDataGet(GtkSelectionData *s)
String Ctrl::Gclipboard::Get(const String& fmt) String Ctrl::Gclipboard::Get(const String& fmt)
{ {
LLOG("Ctrl::Gclipboard::Get " << fmt);
if(fmt == "text") { if(fmt == "text") {
gchar *s = gtk_clipboard_wait_for_text(clipboard); gchar *s = gtk_clipboard_wait_for_text(clipboard);
if(s) { if(s) {
@ -99,16 +100,19 @@ String Ctrl::Gclipboard::Get(const String& fmt)
return Null; return Null;
} }
else else
if(fmt == "image") { if(fmt == "image")
Image img = ImageFromPixbufUnref(gtk_clipboard_wait_for_image(clipboard)); return ImageClipFromPixbufUnref(gtk_clipboard_wait_for_image(clipboard));
return StoreAsString(img); // Not very optimal... else
} if(fmt == "files")
return FilesClipFromUrisFree(gtk_clipboard_wait_for_uris(clipboard));
else else
return GtkDataGet(gtk_clipboard_wait_for_contents(clipboard, GAtom(fmt))); return GtkDataGet(gtk_clipboard_wait_for_contents(clipboard, GAtom(fmt)));
} }
bool Ctrl::Gclipboard::IsAvailable(const String& fmt) bool Ctrl::Gclipboard::IsAvailable(const String& fmt)
{ {
if(fmt == "files")
return gtk_clipboard_wait_is_uris_available(clipboard);
if(fmt == "text") if(fmt == "text")
return gtk_clipboard_wait_is_text_available(clipboard); return gtk_clipboard_wait_is_text_available(clipboard);
if(fmt == "image") if(fmt == "image")
@ -336,12 +340,20 @@ bool IsAvailableFiles(PasteClip& clip)
return clip.IsAvailable("files"); 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) Vector<String> GetFiles(PasteClip& clip)
{ {
GuiLock __; GuiLock __;
Vector<String> f; return GetClipFiles(clip.Get("files"));
return f;
} }
Ptr<Ctrl> Ctrl::sel_ctrl; Ptr<Ctrl> Ctrl::sel_ctrl;

View file

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

View file

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

View file

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

View file

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