mirror of
https://github.com/Ardour/ardour.git
synced 2025-12-06 06:44:57 +01:00
fixes for drag-n-drop broken by use of boost::shared_ptr<T>
git-svn-id: svn://localhost/ardour2/trunk@923 d708f5d6-7413-0410-9779-e7cbd77b26cf
This commit is contained in:
parent
d89e7ff299
commit
41bc62b35b
7 changed files with 156 additions and 134 deletions
|
|
@ -7,6 +7,7 @@ import glob
|
|||
Import('env install_prefix final_prefix config_prefix libraries i18n version')
|
||||
|
||||
gtkardour = env.Copy()
|
||||
gtkmmtests = env.Copy()
|
||||
|
||||
#
|
||||
# this defines the version number of the GTK interface to ardour
|
||||
|
|
@ -49,6 +50,19 @@ gtkardour.Merge ([
|
|||
libraries['jack']
|
||||
])
|
||||
|
||||
gtkmmtests.Append(CXXFLAGS="-DLIBSIGC_DISABLE_DEPRECATED")
|
||||
|
||||
gtkmmtests.Merge ([
|
||||
libraries['gtkmm2'],
|
||||
libraries['glib2'],
|
||||
libraries['glibmm2'],
|
||||
libraries['pangomm'],
|
||||
libraries['atkmm'],
|
||||
libraries['gdkmm2'],
|
||||
libraries['sigc2'],
|
||||
libraries['gtk2']
|
||||
])
|
||||
|
||||
if gtkardour['DMALLOC']:
|
||||
gtkardour.Merge([libraries['dmalloc']])
|
||||
gtkardour.Append(CCFLAGS='-DUSE_DMALLOC')
|
||||
|
|
@ -213,6 +227,10 @@ stest_files=Split("""
|
|||
stest.cc
|
||||
""")
|
||||
|
||||
tt_files=Split ("""
|
||||
tt.cc
|
||||
""")
|
||||
|
||||
extra_sources = []
|
||||
|
||||
vst_files = [ 'vst_pluginui.cc' ]
|
||||
|
|
@ -249,6 +267,7 @@ ardourlib = gtkardour.SharedLibrary(target = 'ardourgtk', source = gtkardour_fil
|
|||
mtest = gtkardour.Program(target = 'mtest', source = mtest_files)
|
||||
itest = gtkardour.Program(target = 'itest', source = itest_files)
|
||||
rcu = gtkardour.Program(target = 'rcu', source = rcu_files)
|
||||
tt = gtkmmtests.Program(target = 'tt', source = tt_files)
|
||||
|
||||
my_subst_dict = { }
|
||||
my_subst_dict['%INSTALL_PREFIX%'] = install_prefix
|
||||
|
|
|
|||
|
|
@ -702,14 +702,15 @@ class Editor : public PublicEditor
|
|||
}
|
||||
Gtk::TreeModelColumn<Glib::ustring> name;
|
||||
Gtk::TreeModelColumn<boost::shared_ptr<ARDOUR::Region> > region;
|
||||
Gtk::TreeModelColumn<Gdk::Color> color_;
|
||||
Gtk::TreeModelColumn<Gdk::Color> color_;
|
||||
};
|
||||
|
||||
RegionListDisplayModelColumns region_list_columns;
|
||||
Gtkmm2ext::DnDTreeView region_list_display;
|
||||
Glib::RefPtr<Gtk::TreeStore> region_list_model;
|
||||
Glib::RefPtr<Gtk::ToggleAction> toggle_full_region_list_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action;
|
||||
RegionListDisplayModelColumns region_list_columns;
|
||||
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Region> > region_list_display;
|
||||
|
||||
Glib::RefPtr<Gtk::TreeStore> region_list_model;
|
||||
Glib::RefPtr<Gtk::ToggleAction> toggle_full_region_list_action;
|
||||
Glib::RefPtr<Gtk::ToggleAction> toggle_show_auto_regions_action;
|
||||
|
||||
void region_list_selection_changed ();
|
||||
bool region_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
|
||||
|
|
@ -772,7 +773,7 @@ class Editor : public PublicEditor
|
|||
NamedSelectionDisplayModelColumns named_selection_columns;
|
||||
Glib::RefPtr<Gtk::TreeStore> named_selection_model;
|
||||
|
||||
Gtkmm2ext::DnDTreeView named_selection_display;
|
||||
Gtkmm2ext::DnDTreeView<ARDOUR::NamedSelection*> named_selection_display;
|
||||
Gtk::ScrolledWindow named_selection_scroller;
|
||||
|
||||
void name_selection();
|
||||
|
|
@ -1429,9 +1430,9 @@ class Editor : public PublicEditor
|
|||
Glib::RefPtr<Gtk::TreeSelection> route_display_selection;
|
||||
|
||||
gint route_list_compare_func (Gtk::TreeModel::iterator, Gtk::TreeModel::iterator);
|
||||
Gtkmm2ext::DnDTreeView route_list_display;
|
||||
Gtk::ScrolledWindow route_list_scroller;
|
||||
Gtk::Menu* route_list_menu;
|
||||
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Route> > route_list_display;
|
||||
Gtk::ScrolledWindow route_list_scroller;
|
||||
Gtk::Menu* route_list_menu;
|
||||
|
||||
bool route_list_display_button_press (GdkEventButton*);
|
||||
bool route_list_selection_filter (const Glib::RefPtr<Gtk::TreeModel>& model, const Gtk::TreeModel::Path& path, bool yn);
|
||||
|
|
|
|||
|
|
@ -488,11 +488,12 @@ Editor::drop_regions (const RefPtr<Gdk::DragContext>& context,
|
|||
const SelectionData& data,
|
||||
guint info, guint time)
|
||||
{
|
||||
const DnDTreeView::SerializedObjectPointers* sr = reinterpret_cast<const DnDTreeView::SerializedObjectPointers*> (data.get_data());
|
||||
const SerializedObjectPointers<boost::shared_ptr<Region> >* sr =
|
||||
reinterpret_cast<const SerializedObjectPointers<boost::shared_ptr<Region> > *> (data.get_data());
|
||||
|
||||
for (uint32_t i = 0; i < sr->cnt; ++i) {
|
||||
|
||||
boost::shared_ptr<Region> r (reinterpret_cast<Region*> (sr->ptr[i]));
|
||||
boost::shared_ptr<Region> r = sr->data[i];
|
||||
boost::shared_ptr<AudioRegion> ar;
|
||||
|
||||
if ((ar = boost::dynamic_pointer_cast<AudioRegion>(r)) != 0) {
|
||||
|
|
|
|||
|
|
@ -156,9 +156,9 @@ RedirectBox::~RedirectBox ()
|
|||
}
|
||||
|
||||
void
|
||||
RedirectBox::object_drop (string type, uint32_t cnt, void** ptr)
|
||||
RedirectBox::object_drop (string type, uint32_t cnt, const boost::shared_ptr<Redirect>* ptr)
|
||||
{
|
||||
if (type != "redirects" || cnt == 0 || ptr == 0) {
|
||||
if (type != "redirects" || cnt == 0 || !ptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -167,7 +167,7 @@ RedirectBox::object_drop (string type, uint32_t cnt, void** ptr)
|
|||
list<boost::shared_ptr<Redirect> > redirects;
|
||||
|
||||
for (uint32_t n = 0; n < cnt; ++n) {
|
||||
redirects.push_back (boost::shared_ptr<Redirect> ((Redirect*) ptr[n]));
|
||||
redirects.push_back (ptr[n]);
|
||||
}
|
||||
|
||||
paste_redirect_list (redirects);
|
||||
|
|
|
|||
|
|
@ -119,10 +119,10 @@ class RedirectBox : public Gtk::HBox
|
|||
|
||||
Gtk::EventBox redirect_eventbox;
|
||||
Gtk::HBox redirect_hpacker;
|
||||
Gtkmm2ext::DnDTreeView redirect_display;
|
||||
Gtkmm2ext::DnDTreeView<boost::shared_ptr<ARDOUR::Redirect> > redirect_display;
|
||||
Gtk::ScrolledWindow redirect_scroller;
|
||||
|
||||
void object_drop (std::string type, uint32_t cnt, void**);
|
||||
void object_drop (std::string type, uint32_t cnt, const boost::shared_ptr<ARDOUR::Redirect>*);
|
||||
|
||||
Width _width;
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ using namespace Gtk;
|
|||
using namespace Glib;
|
||||
using namespace Gtkmm2ext;
|
||||
|
||||
DnDTreeView::DnDTreeView ()
|
||||
DnDTreeViewBase::DnDTreeViewBase ()
|
||||
: TreeView ()
|
||||
{
|
||||
draggable.push_back (TargetEntry ("GTK_TREE_MODEL_ROW", TARGET_SAME_WIDGET));
|
||||
|
|
@ -23,7 +23,7 @@ DnDTreeView::DnDTreeView ()
|
|||
}
|
||||
|
||||
void
|
||||
DnDTreeView::add_drop_targets (list<TargetEntry>& targets)
|
||||
DnDTreeViewBase::add_drop_targets (list<TargetEntry>& targets)
|
||||
{
|
||||
for (list<TargetEntry>::iterator i = targets.begin(); i != targets.end(); ++i) {
|
||||
draggable.push_back (*i);
|
||||
|
|
@ -33,7 +33,7 @@ DnDTreeView::add_drop_targets (list<TargetEntry>& targets)
|
|||
}
|
||||
|
||||
void
|
||||
DnDTreeView::add_object_drag (int column, string type_name)
|
||||
DnDTreeViewBase::add_object_drag (int column, string type_name)
|
||||
{
|
||||
draggable.push_back (TargetEntry (type_name, TargetFlags(0)));
|
||||
data_column = column;
|
||||
|
|
@ -42,86 +42,11 @@ DnDTreeView::add_object_drag (int column, string type_name)
|
|||
enable_model_drag_dest (draggable);
|
||||
}
|
||||
|
||||
DnDTreeView::SerializedObjectPointers*
|
||||
DnDTreeView::serialize_pointers (RefPtr<TreeModel> model, TreeSelection::ListHandle_Path* selection, ustring type)
|
||||
{
|
||||
uint32_t cnt = selection->size();
|
||||
uint32_t sz = (sizeof (void*) * cnt) + sizeof (SerializedObjectPointers);
|
||||
|
||||
cerr << "lets plan to serialize " << cnt << " from selection\n";
|
||||
|
||||
char* buf = new char[sz];
|
||||
SerializedObjectPointers* sr = new (buf) SerializedObjectPointers;
|
||||
|
||||
sr->cnt = cnt;
|
||||
sr->size = sz;
|
||||
|
||||
snprintf (sr->type, sizeof (sr->type), "%s", type.c_str());
|
||||
|
||||
cnt = 0;
|
||||
|
||||
for (TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
|
||||
cerr << "getting next item\n";
|
||||
TreeModel::Row row = *(model->get_iter (*x));
|
||||
row.get_value (data_column, sr->ptr[cnt]);
|
||||
}
|
||||
|
||||
cerr << "returning an SR with size = " << sr->size << endl;
|
||||
return sr;
|
||||
}
|
||||
|
||||
void
|
||||
DnDTreeView::on_drag_data_get(const RefPtr<DragContext>& context, SelectionData& selection_data, guint info, guint time)
|
||||
{
|
||||
if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
|
||||
|
||||
TreeView::on_drag_data_get (context, selection_data, info, time);
|
||||
|
||||
} else if (data_column >= 0) {
|
||||
|
||||
Gtk::TreeSelection::ListHandle_Path selection = get_selection()->get_selected_rows ();
|
||||
SerializedObjectPointers* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
|
||||
selection_data.set (8, (guchar*)sr, sr->size);
|
||||
|
||||
cerr << "selection data set to contain " << sr->size << endl;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
DnDTreeView::on_drag_data_received(const RefPtr<DragContext>& context, int x, int y, const SelectionData& selection_data, guint info, guint time)
|
||||
{
|
||||
if (suggested_action) {
|
||||
/* this is a drag motion callback. just update the status to
|
||||
say that we are still dragging, and that's it.
|
||||
*/
|
||||
suggested_action = Gdk::DragAction (0);
|
||||
TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
|
||||
|
||||
TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
|
||||
|
||||
} else if (data_column >= 0) {
|
||||
|
||||
/* object D-n-D */
|
||||
|
||||
const SerializedObjectPointers* sr = reinterpret_cast<const SerializedObjectPointers *>(selection_data.get_data());
|
||||
|
||||
if (sr) {
|
||||
signal_object_drop (sr->type, sr->cnt, const_cast<void**>(sr->ptr));
|
||||
}
|
||||
|
||||
} else {
|
||||
/* some kind of target type added by the app, which will be handled by a signal handler */
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DnDTreeView::on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
|
||||
DnDTreeViewBase::on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time)
|
||||
{
|
||||
suggested_action = Gdk::DragAction (0);
|
||||
return TreeView::on_drag_drop (context, x, y, time);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,60 +9,136 @@
|
|||
|
||||
namespace Gtkmm2ext {
|
||||
|
||||
class DnDTreeView : public Gtk::TreeView
|
||||
{
|
||||
template<class DataType>
|
||||
struct SerializedObjectPointers {
|
||||
uint32_t size;
|
||||
uint32_t cnt;
|
||||
char type[32];
|
||||
DataType data[0];
|
||||
};
|
||||
|
||||
class DnDTreeViewBase : public Gtk::TreeView
|
||||
{
|
||||
private:
|
||||
public:
|
||||
DnDTreeView ();
|
||||
~DnDTreeView() {}
|
||||
DnDTreeViewBase ();
|
||||
~DnDTreeViewBase() {}
|
||||
|
||||
/* this is the structure pointed to if add_object_drag() is called
|
||||
and a drop happens on a destination which has declared itself
|
||||
willing to accept a target of the type named in the call
|
||||
to add_object_drag().
|
||||
*/
|
||||
|
||||
struct SerializedObjectPointers {
|
||||
uint32_t size;
|
||||
uint32_t cnt;
|
||||
char type[32];
|
||||
void* ptr[0];
|
||||
};
|
||||
|
||||
void add_drop_targets (std::list<Gtk::TargetEntry>&);
|
||||
void add_object_drag (int column, std::string type_name);
|
||||
sigc::signal<void,std::string,uint32_t,void**> signal_object_drop;
|
||||
|
||||
void on_drag_begin(const Glib::RefPtr<Gdk::DragContext>& context) {
|
||||
TreeView::on_drag_begin (context);
|
||||
}
|
||||
void on_drag_end(const Glib::RefPtr<Gdk::DragContext>& context) {
|
||||
TreeView::on_drag_end (context);
|
||||
}
|
||||
void on_drag_data_delete(const Glib::RefPtr<Gdk::DragContext>& context) {
|
||||
TreeView::on_drag_data_delete (context);
|
||||
}
|
||||
void on_drag_leave(const Glib::RefPtr<Gdk::DragContext>& context, guint time) {
|
||||
suggested_action = context->get_suggested_action();
|
||||
TreeView::on_drag_leave (context, time);
|
||||
suggested_action = context->get_suggested_action();
|
||||
TreeView::on_drag_leave (context, time);
|
||||
}
|
||||
|
||||
bool on_drag_motion(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time) {
|
||||
suggested_action = context->get_suggested_action();
|
||||
return TreeView::on_drag_motion (context, x, y, time);
|
||||
}
|
||||
bool on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
|
||||
void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time);
|
||||
void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time);
|
||||
|
||||
private:
|
||||
bool on_drag_drop(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, guint time);
|
||||
|
||||
protected:
|
||||
std::list<Gtk::TargetEntry> draggable;
|
||||
Gdk::DragAction suggested_action;
|
||||
int data_column;
|
||||
|
||||
SerializedObjectPointers* serialize_pointers (Glib::RefPtr<Gtk::TreeModel> m,
|
||||
Gtk::TreeSelection::ListHandle_Path*,
|
||||
Glib::ustring type);
|
||||
};
|
||||
|
||||
template<class DataType>
|
||||
class DnDTreeView : public DnDTreeViewBase
|
||||
{
|
||||
public:
|
||||
DnDTreeView() {}
|
||||
~DnDTreeView() {}
|
||||
|
||||
sigc::signal<void,std::string,uint32_t,const DataType*> signal_object_drop;
|
||||
|
||||
void on_drag_data_get(const Glib::RefPtr<Gdk::DragContext>& context, Gtk::SelectionData& selection_data, guint info, guint time) {
|
||||
if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
|
||||
|
||||
TreeView::on_drag_data_get (context, selection_data, info, time);
|
||||
|
||||
} else if (data_column >= 0) {
|
||||
|
||||
Gtk::TreeSelection::ListHandle_Path selection = get_selection()->get_selected_rows ();
|
||||
SerializedObjectPointers<DataType>* sr = serialize_pointers (get_model(), &selection, selection_data.get_target());
|
||||
selection_data.set (8, (guchar*)sr, sr->size);
|
||||
}
|
||||
}
|
||||
|
||||
void on_drag_data_received(const Glib::RefPtr<Gdk::DragContext>& context, int x, int y, const Gtk::SelectionData& selection_data, guint info, guint time) {
|
||||
if (suggested_action) {
|
||||
/* this is a drag motion callback. just update the status to
|
||||
say that we are still dragging, and that's it.
|
||||
*/
|
||||
suggested_action = Gdk::DragAction (0);
|
||||
TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
|
||||
return;
|
||||
}
|
||||
|
||||
if (selection_data.get_target() == "GTK_TREE_MODEL_ROW") {
|
||||
|
||||
TreeView::on_drag_data_received (context, x, y, selection_data, info, time);
|
||||
|
||||
} else if (data_column >= 0) {
|
||||
|
||||
/* object D-n-D */
|
||||
|
||||
const void* data = selection_data.get_data();
|
||||
const SerializedObjectPointers<DataType>* sr = reinterpret_cast<const SerializedObjectPointers<DataType> *>(data);
|
||||
|
||||
if (sr) {
|
||||
signal_object_drop (sr->type, sr->cnt, sr->data);
|
||||
}
|
||||
|
||||
} else {
|
||||
/* some kind of target type added by the app, which will be handled by a signal handler */
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
SerializedObjectPointers<DataType>* serialize_pointers (Glib::RefPtr<Gtk::TreeModel> model,
|
||||
Gtk::TreeSelection::ListHandle_Path* selection,
|
||||
Glib::ustring type) {
|
||||
|
||||
/* this nasty chunk of code is here because X's DnD protocol (probably other graphics UI's too)
|
||||
requires that we package up the entire data collection for DnD in a single contiguous region
|
||||
(so that it can be trivially copied between address spaces). We don't know the type of DataType so
|
||||
we have to mix-and-match C and C++ programming techniques here to get the right result.
|
||||
|
||||
The C trick is to use the "someType foo[0];" declaration trick to create a zero-sized array at the
|
||||
end of a SerializedObjectPointers<DataType object. Then we allocate a raw memory buffer that extends
|
||||
past that array and thus provides space for however many DataType items we actually want to pass
|
||||
around.
|
||||
|
||||
The C++ trick is to use the placement operator new() syntax to initialize that extra
|
||||
memory properly.
|
||||
*/
|
||||
|
||||
uint32_t cnt = selection->size();
|
||||
uint32_t sz = (sizeof (DataType) * cnt) + sizeof (SerializedObjectPointers<DataType>);
|
||||
|
||||
char* buf = new char[sz];
|
||||
SerializedObjectPointers<DataType>* sr = (SerializedObjectPointers<DataType>*) buf;
|
||||
|
||||
for (uint32_t i = 0; i < cnt; ++i) {
|
||||
new ((void *) &sr->data[i]) DataType ();
|
||||
}
|
||||
|
||||
sr->cnt = cnt;
|
||||
sr->size = sz;
|
||||
snprintf (sr->type, sizeof (sr->type), "%s", type.c_str());
|
||||
|
||||
cnt = 0;
|
||||
|
||||
for (Gtk::TreeSelection::ListHandle_Path::iterator x = selection->begin(); x != selection->end(); ++x, ++cnt) {
|
||||
model->get_iter (*x)->get_value (data_column, sr->data[cnt]);
|
||||
}
|
||||
|
||||
return sr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue