rainbow: Gtk Backend DnD finished

git-svn-id: svn://ultimatepp.org/upp/trunk@5688 f0d560ea-af0d-0410-9eb7-867de7ffcac7
This commit is contained in:
cxl 2012-12-31 17:21:13 +00:00
parent a76dcd46ee
commit dfc2cc1b77
10 changed files with 204 additions and 78 deletions

View file

@ -4,7 +4,7 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LLOG(x) // DLOG(x)
void _DBG_Ungrab(void)
{

View file

@ -4,7 +4,7 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LLOG(x) // DLOG(x)
Ptr<Ctrl> Ctrl::grabwindow;
Ptr<Ctrl> Ctrl::grabpopup;

View file

@ -5,15 +5,10 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LLOG(x) // DLOG(x)
void GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data,
guint info, gpointer user_data)
void Ctrl::GtkSelectionDataSet(GtkSelectionData *selection_data, const String& fmt, const String& data)
{
ArrayMap<String, ClipData>& target = *(ArrayMap<String, ClipData> *)user_data;
LLOG("GtkGetClipData for " << target.GetKey(info));
String fmt = target.GetKey(info);
String data = target[info].Render();
if(fmt == "text") {
String s = data;
gtk_selection_data_set_text(selection_data, (const gchar*)~s, s.GetCount());
@ -34,6 +29,14 @@ void GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data,
}
}
void Ctrl::GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data,
guint info, gpointer user_data)
{
ArrayMap<String, ClipData>& target = *(ArrayMap<String, ClipData> *)user_data;
LLOG("GtkGetClipData for " << target.GetKey(info));
GtkSelectionDataSet(selection_data, target.GetKey(info), target[info].Render());
}
void ClearClipData(GtkClipboard *clipboard, gpointer) {}
Ctrl::Gclipboard::Gclipboard(GdkAtom type)
@ -41,6 +44,25 @@ Ctrl::Gclipboard::Gclipboard(GdkAtom type)
clipboard = gtk_clipboard_get(type);
}
void Ctrl::AddFmt(GtkTargetList *list, const String& fmt, int info)
{
if(fmt == "text")
gtk_target_list_add_text_targets(list, info);
else
if(fmt == "image")
gtk_target_list_add_image_targets(list, info, TRUE);
else
gtk_target_list_add(list, GAtom(fmt), 0, info);
}
GtkTargetList *Ctrl::CreateTargetList(const VectorMap<String, ClipData>& target)
{
GtkTargetList *list = gtk_target_list_new(NULL, 0);
for(int i = 0; i < target.GetCount(); i++)
AddFmt(list, target.GetKey(i), i);
return list;
}
void Ctrl::Gclipboard::Put(const String& fmt, const ClipData& data)
{
GuiLock __;
@ -48,17 +70,7 @@ void Ctrl::Gclipboard::Put(const String& fmt, const ClipData& data)
target.GetAdd(fmt) = data;
GtkTargetList *list = gtk_target_list_new (NULL, 0);
for(int i = 0; i < target.GetCount(); i++) {
String fmt = target.GetKey(i);
if(fmt == "text")
gtk_target_list_add_text_targets(list, i);
else
if(fmt == "image")
gtk_target_list_add_image_targets(list, i, TRUE);
else
gtk_target_list_add(list, GAtom(fmt), 0, i);
}
GtkTargetList *list = CreateTargetList(target);
gint n;
GtkTargetEntry *targets = gtk_target_table_new_from_list(list, &n);
@ -66,8 +78,17 @@ void Ctrl::Gclipboard::Put(const String& fmt, const ClipData& data)
gtk_clipboard_set_with_data(clipboard, targets, n, GtkGetClipData, ClearClipData, &target);
gtk_clipboard_set_can_store(clipboard, NULL, 0);
gtk_target_table_free (targets, n);
gtk_target_list_unref (list);
gtk_target_table_free(targets, n);
gtk_target_list_unref(list);
}
String Ctrl::GtkDataGet(GtkSelectionData *s)
{
if(!s)
return Null;
const guchar *b = gtk_selection_data_get_data(s);
int n = gtk_selection_data_get_length(s);
return n >= 0 && b ? String(b, n) : String();
}
String Ctrl::Gclipboard::Get(const String& fmt)
@ -79,20 +100,15 @@ String Ctrl::Gclipboard::Get(const String& fmt)
g_free(s);
return h;
}
return Null;
}
else
if(fmt == "image") {
Image img = ImageFromPixbufUnref(gtk_clipboard_wait_for_image(clipboard));
return StoreAsString(img); // Not very optimal...
}
else {
GtkSelectionData *s = gtk_clipboard_wait_for_contents(clipboard, GAtom(fmt));
if(s) {
String h(gtk_selection_data_get_data(s), gtk_selection_data_get_length(s));
return h;
}
}
return Null;
else
return GtkDataGet(gtk_clipboard_wait_for_contents(clipboard, GAtom(fmt)));
}
bool Ctrl::Gclipboard::IsAvailable(const String& fmt)
@ -106,7 +122,7 @@ bool Ctrl::Gclipboard::IsAvailable(const String& fmt)
bool PasteClip::IsAvailable(const char *fmt) const
{
DLOG("PasteClip::IsAvailable " << fmt << ", type: " << type);
LLOG("PasteClip::IsAvailable " << fmt << ", type: " << type);
if(type == 1)
return Ctrl::IsDragAvailable(fmt);
return (type == 0 ? Ctrl::gclipboard() : Ctrl::gselection()).IsAvailable(fmt);
@ -114,7 +130,7 @@ bool PasteClip::IsAvailable(const char *fmt) const
String PasteClip::Get(const char *fmt) const
{
DLOG("PasteClip::Get " << fmt << ", type: " << type);
LLOG("PasteClip::Get " << fmt << ", type: " << type);
if(type == 1)
return Ctrl::DragGet(fmt);
return (type == 0 ? Ctrl::gclipboard() : Ctrl::gselection()).Get(fmt);

View file

@ -4,7 +4,7 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LLOG(x) // DLOG(x)
void Ctrl::Create(Ctrl *owner, bool popup)
{

View file

@ -27,7 +27,7 @@
EVENT_TEXT,
};
struct Event : Moveable<Event> {
struct Event0 {
int time;
int windowid;
int type;
@ -37,6 +37,18 @@
int count;
};
struct Event : Moveable<Event, Event0> {
GdkEvent *event;
void Free();
void Set(const Event& e);
Event(const Event& e);
void operator=(const Event& e);
Event();
~Event();
};
struct Win : Moveable<Win> {
int id;
GtkWidget *gtk;
@ -84,7 +96,19 @@
static GtkWidget *dnd_widget;
static GdkDragContext *dnd_context;
static guint dnd_time;
static Ptr<Ctrl> dnd_source;
static const VectorMap<String, ClipData> *dnd_source_data;
static Vector<String> dnd_fmts;
static int dnd_result;
static Image dnd_icon;
static void GtkSelectionDataSet(GtkSelectionData *selection_data, const String& fmt, const String& data);
static void GtkGetClipData(GtkClipboard *clipboard, GtkSelectionData *selection_data, guint info, gpointer user_data);
static void AddFmt(GtkTargetList *list, const String& fmt, int info);
static GtkTargetList *CreateTargetList(const VectorMap<String, ClipData>& target);
static String GtkDataGet(GtkSelectionData *s);
void DndInit();
void DndExit();
@ -113,7 +137,7 @@
public: // really private:
struct Gclipboard {
ArrayMap<String, ClipData> target;
VectorMap<String, ClipData> target;
GtkClipboard *clipboard;
String Get(const String& fmt);

View file

@ -4,19 +4,29 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LLOG(x) // DLOG(x)
// --------------------------------------------------------------------------------------------
Ptr<Ctrl> sDnDSource;
Ptr<Ctrl> Ctrl::dnd_source;
const VectorMap<String, ClipData> *Ctrl::dnd_source_data;
Vector<String> Ctrl::dnd_fmts;
int Ctrl::dnd_result;
Image Ctrl::dnd_icon;
Ctrl * Ctrl::GetDragAndDropSource()
Ctrl *Ctrl::GetDragAndDropSource()
{
return sDnDSource;
return dnd_source;
}
void Ctrl::GtkDragBegin(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
if(IsNull(dnd_icon))
gtk_drag_set_icon_default(context);
else {
ImageGdk m(dnd_icon);
gtk_drag_set_icon_pixbuf(context, m, 0, 0);
}
LLOG("GtkDragBegin");
}
@ -25,21 +35,35 @@ void Ctrl::GtkDragDelete(GtkWidget *widget, GdkDragContext *context, gpointer us
LLOG("GtkDragDelete");
}
void Ctrl::GtkDragGetData(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data,
guint info, guint time, gpointer user_data)
void Ctrl::GtkDragGetData(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data,
guint info, guint time, gpointer user_data)
{
LLOG("GtkDragGetData");
if(info < (guint)dnd_source_data->GetCount())
GtkSelectionDataSet(data, dnd_source_data->GetKey(info), (*dnd_source_data)[info].Render());
else {
info -= dnd_source_data->GetCount();
if(info < (guint)dnd_fmts.GetCount()) {
String fmt = dnd_fmts[info];
GtkSelectionDataSet(data, fmt, dnd_source->GetDropData(fmt));
}
}
}
void Ctrl::GtkDragEnd(GtkWidget *widget, GdkDragContext *context, gpointer user_data)
{
LLOG("GtkDragEnd");
dnd_result = DND_NONE;
GdkDragAction a = gdk_drag_context_get_selected_action(context);
dnd_result = a == GDK_ACTION_MOVE ? DND_MOVE : a == GDK_ACTION_COPY ? DND_COPY : DND_NONE;
dnd_source = NULL;
}
gboolean Ctrl::GtkDragFailed(GtkWidget *widget, GdkDragContext *context, GtkDragResult result,
gpointer user_data)
{
LLOG("GtkDragFailed");
dnd_source = NULL;
return FALSE;
}
@ -58,7 +82,49 @@ Image MakeDragImage(const Image& arrow, const Image& arrow98, Image sample)
int Ctrl::DoDragAndDrop(const char *fmts, const Image& sample, dword actions,
const VectorMap<String, ClipData>& data)
{
return DND_NONE;
LLOG("DoDragAndDrop");
TopWindow *w = GetTopWindow();
if(!w || !w->top)
return DND_NONE;
int gdk_actions = 0;
if(actions & DND_MOVE)
gdk_actions |= GDK_ACTION_MOVE;
if(actions & DND_COPY)
gdk_actions |= GDK_ACTION_COPY;
GtkTargetList *list = CreateTargetList(data);
Vector<String> f = Split(fmts, ';');
dnd_fmts.Clear();
for(int i = 0; i < f.GetCount(); i++) {
AddFmt(list, f[i], data.GetCount() + i);
dnd_fmts.Add(f[i]);
}
dnd_source_data = &data;
dnd_result = DND_NONE;
dnd_source = this;
if(IsNull(sample))
dnd_icon = Null;
else {
Size sz = sample.GetSize();
if(sz.cx > 128)
sz.cx = 128;
if(sz.cy > 128)
sz.cy = 128;
sz += 2;
ImageDraw iw(sz);
iw.DrawRect(sz, White());
DrawFrame(iw, sz, Black());
iw.DrawImage(1, 1, sz.cx, sz.cy, sample);
ImageBuffer b(128, 128);
dnd_icon = iw;
}
gtk_drag_begin(w->top->window, list, GdkDragAction(gdk_actions),
GetMouseLeft() ? 1 : GetMouseMiddle() ? 2 : 3, CurrentEvent.event);
while(dnd_source && GetTopCtrls().GetCount())
ProcessEvents();
dnd_source_data = NULL;
gtk_target_list_unref (list);
LLOG("--DoDragAndDrop");
return dnd_result;
}
// --------------------------------------------------------------------------------------------
@ -89,7 +155,6 @@ void ToIndex(GtkTargetList *target_list, Index<String>& ndx)
ndx.Add(t[i].target);
gtk_target_table_free(t, n);
gtk_target_list_unref(target_list);
DDUMPC(ndx);
}
void Ctrl::DndTargets(GdkDragContext *context)
@ -108,7 +173,6 @@ void Ctrl::DndTargets(GdkDragContext *context)
dnd_text_target.Clear();
for(GList *list = gdk_drag_context_list_targets(context); list; list = g_list_next (list)) {
String g = gdk_atom_name((GdkAtom)list->data);
DDUMP(g);
if(text_targets.Find(g) >= 0) {
dnd_targets.Add("text");
if(dnd_text_target.IsEmpty())
@ -144,7 +208,7 @@ void Ctrl::GtkDragDataReceived(GtkWidget *widget, GdkDragContext *context,
dnd_data = StoreAsString(img); // Not very optimal...
}
else
dnd_data = String(gtk_selection_data_get_data(data), gtk_selection_data_get_length(data));
dnd_data = GtkDataGet(data);
}
bool Ctrl::IsDragAvailable(const char *fmt)
@ -162,16 +226,14 @@ String Ctrl::DragGet(const char *fmt)
dnd_data_wait = true;
dnd_data_fmt = fmt;
int t0 = msecs();
DDUMP(dnd_widget);
DDUMP(dnd_context);
gtk_drag_get_data(dnd_widget, dnd_context,
GAtom(strcmp(fmt, "image") == 0 ? ~dnd_image_target
: strcmp(fmt, "text") == 0 ? ~dnd_text_target : fmt),
: strcmp(fmt, "text") == 0 ? ~dnd_text_target
: fmt),
dnd_time);
while(msecs() - t0 < 1000 && dnd_data_wait)
FetchEvents(true);
LLOG("DragGet data length " << dnd_data.GetLength());
DDUMPHEX(dnd_data);
return dnd_data;
}
@ -189,8 +251,10 @@ PasteClip Ctrl::GtkDnd(GtkWidget *widget, GdkDragContext *context, gint x, gint
clip.paste = paste;
clip.accepted = false;
clip.allowed = DND_MOVE|DND_COPY;
clip.action = gdk_drag_context_get_suggested_action(context) == GDK_ACTION_COPY ? DND_COPY
: DND_MOVE;
gint dummy;
GdkModifierType mod;
gdk_window_get_pointer(gdk_get_default_root_window(), &dummy, &dummy, &mod);
clip.action = mod & GDK_CONTROL_MASK ? DND_COPY : DND_MOVE;
Ctrl *w = DragWnd(user_data);
if(w) {
gint mx, my;
@ -200,6 +264,9 @@ PasteClip Ctrl::GtkDnd(GtkWidget *widget, GdkDragContext *context, gint x, gint
CurrentMousePos = Point(x, y) + w->GetScreenRect().TopLeft();
w->DnD(CurrentMousePos, clip);
}
gdk_drag_status(context, clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? GDK_ACTION_MOVE
: GDK_ACTION_COPY
: GdkDragAction(0), time);
return clip;
}
@ -209,9 +276,6 @@ gboolean Ctrl::GtkDragMotion(GtkWidget *widget, GdkDragContext *context, gint x,
LLOG("GtkDragMotion");
PasteClip clip = GtkDnd(widget, context, x, y, time, user_data, false);
gdk_drag_status(context, clip.IsAccepted() ? clip.GetAction() == DND_MOVE ? GDK_ACTION_MOVE
: GDK_ACTION_COPY
: GdkDragAction(0), time);
g_object_unref(widget);
g_object_unref(context);
return TRUE;
@ -236,6 +300,8 @@ gboolean Ctrl::GtkDragDrop(GtkWidget *widget, GdkDragContext *context, gint x, g
return TRUE;
}
// -----------------------------------------------------------------------------------------
void Ctrl::DndInit()
{
GtkWidget *w = top->window;

View file

@ -210,6 +210,43 @@ int Ctrl::DoButtonEvent(GdkEvent *event, bool press)
return Null;
}
Ctrl::Event::Event()
{
event = NULL;
}
void Ctrl::Event::Free()
{
if(event) {
gdk_event_free(event);
event = NULL;
}
}
void Ctrl::Event::Set(const Event& e)
{
*(Event0 *)this = e;
event = gdk_event_copy(e.event);
}
Ctrl::Event::~Event()
{
Free();
}
Ctrl::Event::Event(const Event& e)
{
Set(e);
}
void Ctrl::Event::operator=(const Event& e)
{
if(this == &e)
return;
Free();
Set(e);
}
void Ctrl::AddEvent(gpointer user_data, int type, const Value& value)
{
if(Events.GetCount() > 50000)
@ -230,6 +267,7 @@ void Ctrl::AddEvent(gpointer user_data, int type, const Value& value)
e.mousepos = EventMousePos;
e.state = EventState;
e.count = 1;
e.event = gtk_get_current_event();
}
void Ctrl::IMCommit(GtkIMContext *context, gchar *str, gpointer user_data)

View file

@ -16,7 +16,7 @@ bool ImageGdk::Set(const Image& m)
{
Free();
if(m.GetSerialId() != img.GetSerialId()) {
img = m;
img = Unmultiply(m);
if(!IsNull(img)) {
Size sz = img.GetSize();
pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, true, 8, sz.cx, sz.cy);

View file

@ -4,7 +4,7 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LLOG(x) // DLOG(x)
void TopWindow::SyncSizeHints()
{
@ -101,7 +101,6 @@ void TopWindow::Open(Ctrl *owner)
SetRect(GetPrimaryScreenArea());
else
CenterRect(owner);
DDUMP(GetRect());
IgnoreMouseUp();
Create(owner, false);
g_signal_connect(top->window, "window-state-event", G_CALLBACK(StateEvent), this);
@ -112,9 +111,6 @@ void TopWindow::Open(Ctrl *owner)
state = OVERLAPPED;
SetMode(q);
SyncTopMost();
gtk_window_set_type_hint(gtk(), tool ? GDK_WINDOW_TYPE_HINT_UTILITY
: GetOwner() ? GDK_WINDOW_TYPE_HINT_DIALOG
: GDK_WINDOW_TYPE_HINT_NORMAL);
}
void TopWindow::Open()

View file

@ -4,15 +4,7 @@
NAMESPACE_UPP
#define LLOG(x) DLOG(x)
#define LOGTIMING 0
#ifdef _DEBUG
#define LOGMESSAGES 0
#endif
#define ELOGW(x) // RLOG(GetSysTime() << ": " << x) // Only activate in MT!
#define ELOG(x) // RLOG(GetSysTime() << ": " << x)
#define LLOG(x) // DLOG(x)
Vector<Ctrl::Win> Ctrl::wins;
@ -73,7 +65,6 @@ Vector<Ctrl *> Ctrl::GetTopCtrls()
void Ctrl::SetMouseCursor(const Image& image)
{
GuiLock __;
DTIMING("SetMouseCursor");
int64 id = image.GetSerialId();
Ctrl *topctrl = NULL;
Top *top = NULL;
@ -333,10 +324,7 @@ void Ctrl::SetWndForeground0()
bool Ctrl::IsWndForeground() const
{
GuiLock __;
DLOG("IsWndForeground");
DDUMP(top);
DDUMP(gtk());
DDUMP(gtk_window_is_active(gtk()));
LLOG("IsWndForeground");
return top && gtk_window_is_active(gtk());
}
@ -352,12 +340,10 @@ void Ctrl::WndEnable0(bool *b)
void Ctrl::SetWndFocus0(bool *b)
{
GuiLock __;
DLOG("SetWndFocus0 " << top);
LLOG("SetWndFocus0 " << top);
if(top) {
DLOG("SetWndFocus0 DO " << top->window);
DDUMP(gtk_widget_get_can_focus(top->window));
LLOG("SetWndFocus0 DO " << top->window);
gdk_window_focus(gdk(), CurrentTime);
// gtk_window_present(gtk());
*b = true;
}
}