#include #include static GtkWidget *main_window = NULL; #ifdef USE_GTK_DRAG_BEGIN static gboolean in_drag_operation = FALSE; static gint drag_button = 0; static gint drag_x = 0; static gint drag_y = 0; #endif #define DRAG_TEXT_URI_LIST 1 #define DRAG_TEXT_PLAIN 2 static GtkTargetEntry drag_targets[] = { { "text/uri-list", 0, DRAG_TEXT_URI_LIST }, { "text/plain", 0, DRAG_TEXT_PLAIN } }; static void make_uri_list(gchar ***uri_list) { gchar **list; gchar *path; GDir *dir; const gchar *name; struct stat sb; GList *files = NULL; GList *cur; gchar *tmp; gchar *p; *uri_list = NULL; path = g_get_current_dir(); dir = g_dir_open(path, 0, NULL); if (dir == NULL) { g_free(path); return; } while ((name = g_dir_read_name(dir)) != NULL) { tmp = g_build_filename(path, name, NULL); if (g_stat(tmp, &sb) == 0 && (sb.st_mode & S_IFMT) == S_IFREG) { p = g_strrstr(name, "."); if (p != NULL) { p++; if (g_ascii_strcasecmp(p, "c") == 0 || g_ascii_strcasecmp(p, "txt") == 0 || g_ascii_strcasecmp(p, "htm") == 0 || g_ascii_strcasecmp(p, "html") == 0) { files = g_list_append(files, tmp); continue; } } } g_free(tmp); } g_dir_close(dir); g_free(path); if (g_list_length(files) > 0) { list = g_new0(gchar *, g_list_length(files) + 1); *uri_list = list; for (cur = g_list_first(files); cur != NULL; cur = g_list_next(cur)) { p = g_filename_to_uri(cur->data, NULL, NULL); if (p == NULL) { continue; } *list++ = p; } } *list = NULL; g_list_foreach(files, (GFunc)g_free, NULL); g_list_free(files); } void drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer user_data) { g_print("<<< DRAG BEGIN >>>\n"); } void drag_data_get(GtkWidget *widget, GdkDragContext *context, GtkSelectionData *data, guint info, guint time_, gpointer user_data) { g_print("<<< DRAG DATA GET >>>\n"); g_print("data->target=%d %s\n", data->target, gdk_atom_name((GdkAtom)data->target)); g_print("info=%d\n", info); if (info == DRAG_TEXT_URI_LIST) { gchar **uri_list = NULL; gchar **ptr; make_uri_list(&uri_list); if (uri_list != NULL) { gtk_selection_data_set_uris(data, uri_list); for (ptr = uri_list; *ptr != NULL; ptr++) { g_free(*ptr); } g_free(uri_list); } } else if (info == DRAG_TEXT_PLAIN) { const char *msg = "hello, world!"; gtk_selection_data_set_text(data, msg, strlen(msg)); } } void drag_data_delete(GtkWidget *widget, GdkDragContext *context, gpointer user_data) { g_print("<<< DRAG DATA DELETE >>>\n"); } void drag_end(GtkWidget *widget, GdkDragContext *context, gpointer user_data) { g_print("<<< DRAG END >>>\n"); #ifdef USE_GTK_DRAG_BEGIN in_drag_operation = FALSE; drag_button = 0; #endif } #ifdef USE_GTK_DRAG_BEGIN gboolean button_press_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { g_print("<<< BUTTON PRESS EVENT >>>\n"); if (in_drag_operation) { return FALSE; } if (event == NULL) { return FALSE; } if (event->button != 1 && event->button != 2 && event->button != 3) { return FALSE; } if (drag_button == 0) { drag_button = event->button; drag_x = (gint)event->x; drag_y = (gint)event->y; } else if (event->button < drag_button) { drag_button = event->button; } return FALSE; } #endif #ifdef USE_GTK_DRAG_BEGIN gboolean button_release_event(GtkWidget *widget, GdkEventButton *event, gpointer user_data) { g_print("<<< BUTTON RELEASE EVENT >>>\n"); if (in_drag_operation) { return FALSE; } if (event == NULL) { return FALSE; } if (event->button != 1 && event->button != 2 && event->button != 3) { return FALSE; } drag_button = 0; return FALSE; } #endif #ifdef USE_GTK_DRAG_BEGIN gboolean motion_notify_event(GtkWidget *widget, GdkEventMotion *event, gpointer user_data) { g_print("<<< MOTION NOTIFY EVENT >>>\n"); if (in_drag_operation) { return FALSE; } if (event == NULL) { return FALSE; } if (drag_button == 0) { return FALSE; } if (gtk_drag_check_threshold(widget, drag_x, drag_y, (gint)event->x, (gint)event->y)) { GtkTargetList *list; in_drag_operation = TRUE; list = gtk_target_list_new(drag_targets,sizeof(drag_targets) / sizeof(drag_targets[0])); gtk_drag_begin(widget, list, GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK, drag_button, (GdkEvent *)event); gtk_target_list_unref(list); } return FALSE; } #endif #ifdef USE_GTK_DRAG_BEGIN gboolean leave_notify_event(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data) { g_print("<<< LEAVE NOTIFY EVENT >>>\n"); if (!in_drag_operation) { drag_button = 0; } return FALSE; } #endif int main(int argc, char **argv) { GtkWidget *window; GtkWidget *button; gtk_init(&argc, &argv); window = gtk_window_new(GTK_WINDOW_TOPLEVEL); gtk_window_set_title(GTK_WINDOW(window), "dnd drag test"); gtk_window_set_default_size(GTK_WINDOW(window), 300, 150); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(gtk_main_quit), NULL); button = gtk_button_new_with_label("ドラッグして!"); g_signal_connect(G_OBJECT(button), "drag-begin", G_CALLBACK(drag_begin), NULL); g_signal_connect(G_OBJECT(button), "drag-data-get", G_CALLBACK(drag_data_get), NULL); g_signal_connect(G_OBJECT(button), "drag-data-delete", G_CALLBACK(drag_data_delete), NULL); g_signal_connect(G_OBJECT(button), "drag-end", G_CALLBACK(drag_end), NULL); #ifdef USE_GTK_DRAG_BEGIN g_signal_connect(G_OBJECT(button), "button-press-event", G_CALLBACK(button_press_event), NULL); g_signal_connect(G_OBJECT(button), "button-release-event", G_CALLBACK(button_release_event), NULL); g_signal_connect(G_OBJECT(button), "motion-notify-event", G_CALLBACK(motion_notify_event), NULL); g_signal_connect(G_OBJECT(button), "leave-notify-event", G_CALLBACK(leave_notify_event), NULL); gtk_widget_set_events(button, gtk_widget_get_events(button) | GDK_POINTER_MOTION_MASK); #else gtk_drag_source_set(button, GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK, drag_targets, sizeof(drag_targets) / sizeof(drag_targets[0]), GDK_ACTION_COPY | GDK_ACTION_MOVE | GDK_ACTION_LINK | GDK_ACTION_ASK); #endif gtk_container_add(GTK_CONTAINER(window), button); gtk_widget_show_all(window); gtk_main(); return 0; }