static gint gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxDropSource *source ) { source->GiveFeedback( ConvertFromGTK(source->m_dragContext->action) ); return 0; }
wxDragResult wxDropTarget::GTKFigureOutSuggestedAction() { if (!m_dragContext) return wxDragError; // GTK+ always supposes that we want to copy the data by default while we // might want to move it, so examine not only suggested_action - which is // only good if we don't have our own preferences - but also the actions // field wxDragResult suggested_action = wxDragNone; const GdkDragAction actions = gdk_drag_context_get_actions(m_dragContext); if (GetDefaultAction() == wxDragNone) { // use default action set by wxDropSource::DoDragDrop() if ( (gs_flagsForDrag & wxDrag_DefaultMove) == wxDrag_DefaultMove && (actions & GDK_ACTION_MOVE)) { // move is requested by the program and allowed by GTK+ - do it, even // though suggested_action may be currently wxDragCopy suggested_action = wxDragMove; } else // use whatever GTK+ says we should { suggested_action = ConvertFromGTK(gdk_drag_context_get_suggested_action(m_dragContext)); #if 0 // RR: I don't understand the code below: if the drag comes from // a different app, the gs_flagsForDrag is invalid; if it // comes from the same wx app, then GTK+ hopefully won't // suggest something we didn't allow in the frist place // in DoDrop() if ( (suggested_action == wxDragMove) && !(gs_flagsForDrag & wxDrag_AllowMove) ) { // we're requested to move but we can't suggested_action = wxDragCopy; } #endif } } else if (GetDefaultAction() == wxDragMove && (actions & GDK_ACTION_MOVE)) { suggested_action = wxDragMove; } else { if (actions & GDK_ACTION_COPY) suggested_action = wxDragCopy; else if (actions & GDK_ACTION_MOVE) suggested_action = wxDragMove; else if (actions & GDK_ACTION_LINK) suggested_action = wxDragLink; else suggested_action = wxDragNone; } return suggested_action; }
static gint gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxDropSource *source ) { // don't need to install idle handler, its done from "event" signal source->GiveFeedback( ConvertFromGTK(source->m_dragContext->action) ); return 0; }
static void source_drag_data_get (GtkWidget *WXUNUSED(widget), GdkDragContext *context, GtkSelectionData *selection_data, guint WXUNUSED(info), guint WXUNUSED(time), wxDropSource *drop_source ) { wxDataFormat format( selection_data->target ); wxLogTrace(TRACE_DND, wxT("Drop source: format requested: %s"), format.GetId().c_str()); drop_source->m_retValue = wxDragError; wxDataObject *data = drop_source->GetDataObject(); if (!data) { wxLogTrace(TRACE_DND, wxT("Drop source: no data object") ); return; } if (!data->IsSupportedFormat(format)) { wxLogTrace(TRACE_DND, wxT("Drop source: unsupported format") ); return; } if (data->GetDataSize(format) == 0) { wxLogTrace(TRACE_DND, wxT("Drop source: empty data") ); return; } size_t size = data->GetDataSize(format); // printf( "data size: %d.\n", (int)data_size ); guchar *d = new guchar[size]; if (!data->GetDataHere( format, (void*)d )) { delete[] d; return; } drop_source->m_retValue = ConvertFromGTK( context->action ); gtk_selection_data_set( selection_data, selection_data->target, 8, // 8-bit d, size ); delete[] d; }
static gint gtk_dnd_window_configure_callback( GtkWidget *WXUNUSED(widget), GdkEventConfigure *WXUNUSED(event), wxDropSource *source ) { if (g_isIdle) wxapp_install_idle_handler(); source->GiveFeedback( ConvertFromGTK(source->m_dragContext->action) ); return 0; }
static void target_drag_data_received( GtkWidget *WXUNUSED(widget), GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint WXUNUSED(info), guint time, wxDropTarget *drop_target ) { if (g_isIdle) wxapp_install_idle_handler(); /* Owen Taylor: "call gtk_drag_finish() with success == TRUE" */ if ((data->length <= 0) || (data->format != 8)) { /* negative data length and non 8-bit data format qualifies for junk */ gtk_drag_finish (context, FALSE, FALSE, time); return; } #ifdef __WXDEBUG__ wxLogTrace(TRACE_DND, wxT( "Drop target: data received event") ); #endif /* inform the wxDropTarget about the current GtkSelectionData. this is only valid for the duration of this call */ drop_target->SetDragData( data ); wxDragResult result = ConvertFromGTK(context->action); if ( wxIsDragResultOk( drop_target->OnData( x, y, result ) ) ) { #ifdef __WXDEBUG__ wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned true") ); #endif /* tell GTK that data transfer was successful */ gtk_drag_finish( context, TRUE, FALSE, time ); } else { #ifdef __WXDEBUG__ wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned FALSE") ); #endif /* tell GTK that data transfer was not successful */ gtk_drag_finish( context, FALSE, FALSE, time ); } /* after this, invalidate the drop_target's drag data */ drop_target->SetDragData( (GtkSelectionData*) NULL ); }
static void target_drag_data_received( GtkWidget *WXUNUSED(widget), GdkDragContext *context, gint x, gint y, GtkSelectionData *data, guint WXUNUSED(info), guint time, wxDropTarget *drop_target ) { /* Owen Taylor: "call gtk_drag_finish() with success == TRUE" */ if (gtk_selection_data_get_length(data) <= 0 || gtk_selection_data_get_format(data) != 8) { /* negative data length and non 8-bit data format qualifies for junk */ gtk_drag_finish (context, FALSE, FALSE, time); return; } wxLogTrace(TRACE_DND, wxT( "Drop target: data received event") ); /* inform the wxDropTarget about the current GtkSelectionData. this is only valid for the duration of this call */ drop_target->GTKSetDragData( data ); wxDragResult result = ConvertFromGTK(gdk_drag_context_get_selected_action(context)); if ( wxIsDragResultOk( drop_target->OnData( x, y, result ) ) ) { wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned true") ); /* tell GTK that data transfer was successful */ gtk_drag_finish( context, TRUE, FALSE, time ); } else { wxLogTrace(TRACE_DND, wxT( "Drop target: OnData returned FALSE") ); /* tell GTK that data transfer was not successful */ gtk_drag_finish( context, FALSE, FALSE, time ); } /* after this, invalidate the drop_target's drag data */ drop_target->GTKSetDragData( NULL ); }
wxDragResult wxDropSource::DoDragDrop(int flags) { wxCHECK_MSG( m_data && m_data->GetFormatCount(), wxDragNone, wxT("Drop source: no data") ); // still in drag if (g_blockEventsOnDrag) return wxDragNone; // don't start dragging if no button is down if (g_lastButtonNumber == 0) return wxDragNone; // we can only start a drag after a mouse event if (g_lastMouseEvent == NULL) return wxDragNone; // disabled for now g_blockEventsOnDrag = true; RegisterWindow(); m_waiting = true; GtkTargetList *target_list = gtk_target_list_new( (GtkTargetEntry*) NULL, 0 ); wxDataFormat *array = new wxDataFormat[ m_data->GetFormatCount() ]; m_data->GetAllFormats( array ); size_t count = m_data->GetFormatCount(); for (size_t i = 0; i < count; i++) { GdkAtom atom = array[i]; #ifdef __WXDEBUG__ wxLogTrace(TRACE_DND, wxT("Drop source: Supported atom %s"), gdk_atom_name( atom )); #endif gtk_target_list_add( target_list, atom, 0, 0 ); } delete[] array; int action = GDK_ACTION_COPY; if ( flags & wxDrag_AllowMove ) action |= GDK_ACTION_MOVE; // VZ: as we already use g_blockEventsOnDrag it shouldn't be that bad // to use a global to pass the flags to the drop target but I'd // surely prefer a better way to do it gs_flagsForDrag = flags; GdkDragContext *context = gtk_drag_begin( m_widget, target_list, (GdkDragAction)action, g_lastButtonNumber, // number of mouse button which started drag (GdkEvent*) g_lastMouseEvent ); m_dragContext = context; PrepareIcon( action, context ); while (m_waiting) gtk_main_iteration(); m_retValue = ConvertFromGTK(context->action); if ( m_retValue == wxDragNone ) m_retValue = wxDragCancel; g_blockEventsOnDrag = false; UnregisterWindow(); return m_retValue; }
static gboolean target_drag_motion( GtkWidget *WXUNUSED(widget), GdkDragContext *context, gint x, gint y, guint time, wxDropTarget *drop_target ) { if (g_isIdle) wxapp_install_idle_handler(); /* Owen Taylor: "if the coordinates not in a drop zone, return FALSE, otherwise call gtk_drag_status() and return TRUE" */ /* inform the wxDropTarget about the current GdkDragContext. this is only valid for the duration of this call */ drop_target->SetDragContext( context ); // GTK+ always supposes that we want to copy the data by default while we // might want to move it, so examine not only suggested_action - which is // only good if we don't have our own preferences - but also the actions // field wxDragResult result; if (drop_target->GetDefaultAction() == wxDragNone) { // use default action set by wxDropSource::DoDragDrop() if ( (gs_flagsForDrag & wxDrag_DefaultMove) == wxDrag_DefaultMove && (context->actions & GDK_ACTION_MOVE ) ) { // move is requested by the program and allowed by GTK+ - do it, even // though suggested_action may be currently wxDragCopy result = wxDragMove; } else // use whatever GTK+ says we should { result = ConvertFromGTK(context->suggested_action); if ( (result == wxDragMove) && !(gs_flagsForDrag & wxDrag_AllowMove) ) { // we're requested to move but we can't result = wxDragCopy; } } } else if (drop_target->GetDefaultAction() == wxDragMove && (context->actions & GDK_ACTION_MOVE)) { result = wxDragMove; } else { if (context->actions & GDK_ACTION_COPY) result = wxDragCopy; else if (context->actions & GDK_ACTION_MOVE) result = wxDragMove; else result = wxDragNone; } if (drop_target->m_firstMotion) { /* the first "drag_motion" event substitutes a "drag_enter" event */ result = drop_target->OnEnter( x, y, result ); } else { /* give program a chance to react (i.e. to say no by returning FALSE) */ result = drop_target->OnDragOver( x, y, result ); } bool ret = wxIsDragResultOk( result ); if (ret) { GdkDragAction action; if (result == wxDragCopy) action = GDK_ACTION_COPY; else if (result == wxDragLink) action = GDK_ACTION_LINK; else action = GDK_ACTION_MOVE; gdk_drag_status( context, action, time ); } /* after this, invalidate the drop_target's GdkDragContext */ drop_target->SetDragContext( (GdkDragContext*) NULL ); /* this has to be done because GDK has no "drag_enter" event */ drop_target->m_firstMotion = false; return ret; }