diff --git a/rainbow/Gtk/App.cpp b/rainbow/Gtk/App.cpp index bbec799fc..d1b19e9ab 100644 --- a/rainbow/Gtk/App.cpp +++ b/rainbow/Gtk/App.cpp @@ -4,7 +4,7 @@ NAMESPACE_UPP -#define LLOG(x) DLOG(x) +#define LLOG(x) // DLOG(x) void _DBG_Ungrab(void) { diff --git a/rainbow/Gtk/Capture.cpp b/rainbow/Gtk/Capture.cpp index b570c24be..ac3fc3172 100644 --- a/rainbow/Gtk/Capture.cpp +++ b/rainbow/Gtk/Capture.cpp @@ -4,7 +4,7 @@ NAMESPACE_UPP -#define LLOG(x) DLOG(x) +#define LLOG(x) // DLOG(x) Ptr Ctrl::grabwindow; Ptr Ctrl::grabpopup; diff --git a/rainbow/Gtk/Clip.cpp b/rainbow/Gtk/Clip.cpp index 4e190a5fe..89b974396 100644 --- a/rainbow/Gtk/Clip.cpp +++ b/rainbow/Gtk/Clip.cpp @@ -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& target = *(ArrayMap *)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& target = *(ArrayMap *)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& 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); diff --git a/rainbow/Gtk/Create.cpp b/rainbow/Gtk/Create.cpp index fddff7f87..be5ad31af 100644 --- a/rainbow/Gtk/Create.cpp +++ b/rainbow/Gtk/Create.cpp @@ -4,7 +4,7 @@ NAMESPACE_UPP -#define LLOG(x) DLOG(x) +#define LLOG(x) // DLOG(x) void Ctrl::Create(Ctrl *owner, bool popup) { diff --git a/rainbow/Gtk/Ctrl.h b/rainbow/Gtk/Ctrl.h index 33287f552..4055e751d 100644 --- a/rainbow/Gtk/Ctrl.h +++ b/rainbow/Gtk/Ctrl.h @@ -27,7 +27,7 @@ EVENT_TEXT, }; - struct Event : Moveable { + struct Event0 { int time; int windowid; int type; @@ -37,6 +37,18 @@ int count; }; + struct Event : Moveable { + GdkEvent *event; + + void Free(); + void Set(const Event& e); + Event(const Event& e); + void operator=(const Event& e); + + Event(); + ~Event(); + }; + struct Win : Moveable { int id; GtkWidget *gtk; @@ -84,7 +96,19 @@ static GtkWidget *dnd_widget; static GdkDragContext *dnd_context; static guint dnd_time; + + static Ptr dnd_source; + static const VectorMap *dnd_source_data; + static Vector 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& target); + static String GtkDataGet(GtkSelectionData *s); + void DndInit(); void DndExit(); @@ -113,7 +137,7 @@ public: // really private: struct Gclipboard { - ArrayMap target; + VectorMap target; GtkClipboard *clipboard; String Get(const String& fmt); diff --git a/rainbow/Gtk/DnD.cpp b/rainbow/Gtk/DnD.cpp index 2aef1090a..1ba6bc063 100644 --- a/rainbow/Gtk/DnD.cpp +++ b/rainbow/Gtk/DnD.cpp @@ -4,19 +4,29 @@ NAMESPACE_UPP -#define LLOG(x) DLOG(x) +#define LLOG(x) // DLOG(x) // -------------------------------------------------------------------------------------------- -Ptr sDnDSource; +Ptr Ctrl::dnd_source; +const VectorMap *Ctrl::dnd_source_data; +Vector 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& 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 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& 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; diff --git a/rainbow/Gtk/Event.cpp b/rainbow/Gtk/Event.cpp index ac79cc6e2..910293a72 100644 --- a/rainbow/Gtk/Event.cpp +++ b/rainbow/Gtk/Event.cpp @@ -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) diff --git a/rainbow/Gtk/GdkImage.cpp b/rainbow/Gtk/GdkImage.cpp index d9c4371b4..b8a59fafb 100644 --- a/rainbow/Gtk/GdkImage.cpp +++ b/rainbow/Gtk/GdkImage.cpp @@ -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); diff --git a/rainbow/Gtk/Top.cpp b/rainbow/Gtk/Top.cpp index 43de23019..f58055159 100644 --- a/rainbow/Gtk/Top.cpp +++ b/rainbow/Gtk/Top.cpp @@ -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() diff --git a/rainbow/Gtk/Wnd.cpp b/rainbow/Gtk/Wnd.cpp index bf33ada28..4f063a968 100644 --- a/rainbow/Gtk/Wnd.cpp +++ b/rainbow/Gtk/Wnd.cpp @@ -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::wins; @@ -73,7 +65,6 @@ Vector 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; } }