From 4650f7ec144ad9b35ddf6b6ae20818ec79b8613d Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 15:43:01 -0400 Subject: [PATCH 1/9] gtk-demo: Cosmetic improvement to listbox2 demo Make the checkbutton and the check align vertically. --- demos/gtk-demo/listbox2.ui | 2 ++ 1 file changed, 2 insertions(+) diff --git a/demos/gtk-demo/listbox2.ui b/demos/gtk-demo/listbox2.ui index 54975c887b..c4f4700caa 100644 --- a/demos/gtk-demo/listbox2.ui +++ b/demos/gtk-demo/listbox2.ui @@ -120,6 +120,8 @@ object-select-symbolic end center + 10 + 10 0 From 2bf9ae005fc0fb9f51202b5e6dc7525ae47464da Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 15:43:46 -0400 Subject: [PATCH 2/9] Adwaita: Small improvement for dropdown Put some space between the arrow and the text. This was noticable in the new listbox2 demo. --- gtk/theme/Adwaita/_common.scss | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gtk/theme/Adwaita/_common.scss b/gtk/theme/Adwaita/_common.scss index deeaed97f9..cb4ba39680 100644 --- a/gtk/theme/Adwaita/_common.scss +++ b/gtk/theme/Adwaita/_common.scss @@ -1197,6 +1197,10 @@ spinbutton { **************/ dropdown > popover.menu.background > contents { padding: 0; } //allow search entries with no margin +dropdown > button > box { + border-spacing: 6px; +} + dropdown, combobox { arrow { From a85fc0008c9618b4999f3851ffb9ff01db2a03dc Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 16:00:19 -0400 Subject: [PATCH 3/9] wayland: Don't send invalid anchor rectangles When we send an anchor rectangle with a width or height of 0, mutter reponds with "Invalid anchor rectangle size". So, don't do that. This was seen as sudden disappearance of gtk4-demo when you click the fishbowl benchmark all the way through to the menubuttons. Fixes: #3027 --- gdk/wayland/gdksurface-wayland.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index 46dd4a3284..a7ecb7b19b 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -2318,8 +2318,8 @@ create_dynamic_positioner (GdkSurface *surface, real_anchor_rect_x = anchor_rect->x - parent->shadow_left; real_anchor_rect_y = anchor_rect->y - parent->shadow_top; - anchor_rect_width = anchor_rect->width; - anchor_rect_height = anchor_rect->height; + anchor_rect_width = MAX (anchor_rect->width, 1); + anchor_rect_height = MAX (anchor_rect->height, 1); gdk_popup_layout_get_offset (layout, &rect_anchor_dx, &rect_anchor_dy); From b69dc3d054e3d5d24b14f473090f3932c53e456c Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 16:36:00 -0400 Subject: [PATCH 4/9] gtk-demo: Add warnings to the themes demo Add a warning that the flickering here may be hazardous to photosensitive viewers. --- demos/gtk-demo/themes.c | 78 +++++++++++++++------------------------- demos/gtk-demo/themes.ui | 9 +++++ 2 files changed, 38 insertions(+), 49 deletions(-) diff --git a/demos/gtk-demo/themes.c b/demos/gtk-demo/themes.c index 83d8073b4c..1275117975 100644 --- a/demos/gtk-demo/themes.c +++ b/demos/gtk-demo/themes.c @@ -1,6 +1,9 @@ /* Benchmark/Themes * * This demo switches themes like a maniac, like some of you. + * + * Warning: This demo involves rapidly flashing changes and may + * be hazardous to photosensitive viewers. */ #include @@ -123,51 +126,12 @@ change_theme (GtkWidget *widget, return G_SOURCE_CONTINUE; } -static void -clicked (GtkGestureClick *gesture, - int n_press, - double x, - double y, - gpointer data) -{ - GtkWidget *window; - GdkEvent *event; - GdkModifierType state; - - window = gtk_widget_get_ancestor (gtk_event_controller_get_widget (GTK_EVENT_CONTROLLER (gesture)), GTK_TYPE_WINDOW); - - event = gtk_gesture_get_last_event (GTK_GESTURE (gesture), NULL); - state = gdk_event_get_modifier_state (event); - - if (state & GDK_CONTROL_MASK) - { - if (tick_cb) - { - gtk_widget_remove_tick_callback (window, tick_cb); - tick_cb = 0; - } - - change_theme (window, NULL, data); - } - else - { - if (tick_cb) - { - gtk_widget_remove_tick_callback (window, tick_cb); - tick_cb = 0; - } - else - { - tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL); - } - } -} - static void toggle_cycle (GObject *button, GParamSpec *pspec, gpointer data) { + GtkWidget *warning = data; gboolean active; GtkWidget *window; @@ -177,7 +141,7 @@ toggle_cycle (GObject *button, if (active && !tick_cb) { - tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL); + gtk_window_present (GTK_WINDOW (warning)); } else if (!active && tick_cb) { @@ -186,6 +150,25 @@ toggle_cycle (GObject *button, } } +static void +warning_closed (GtkDialog *warning, + int response_id, + gpointer data) +{ + GtkWidget *window; + GtkWidget *button; + + gtk_widget_hide (GTK_WIDGET (warning)); + + window = gtk_widget_get_ancestor (GTK_WIDGET (data), GTK_TYPE_WINDOW); + button = GTK_WIDGET (g_object_get_data (G_OBJECT (window), "button")); + + if (response_id == GTK_RESPONSE_OK) + tick_cb = gtk_widget_add_tick_callback (window, change_theme, data, NULL); + else + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), FALSE); +} + GtkWidget * do_themes (GtkWidget *do_widget) { @@ -194,10 +177,9 @@ do_themes (GtkWidget *do_widget) if (!window) { GtkBuilder *builder; - GtkWidget *header; GtkWidget *button; GtkWidget *label; - GtkGesture *gesture; + GtkWidget *warning; builder = gtk_builder_new_from_resource ("/themes/themes.ui"); window = GTK_WIDGET (gtk_builder_get_object (builder, "window")); @@ -205,15 +187,13 @@ do_themes (GtkWidget *do_widget) gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); - header = GTK_WIDGET (gtk_builder_get_object (builder, "header")); label = GTK_WIDGET (gtk_builder_get_object (builder, "fps")); - - gesture = gtk_gesture_click_new (); - g_signal_connect (gesture, "pressed", G_CALLBACK (clicked), label); - gtk_widget_add_controller (header, GTK_EVENT_CONTROLLER (gesture)); + warning = GTK_WIDGET (gtk_builder_get_object (builder, "warning")); + g_signal_connect (warning, "response", G_CALLBACK (warning_closed), label); button = GTK_WIDGET (gtk_builder_get_object (builder, "toggle")); - g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), label); + g_object_set_data (G_OBJECT (window), "button", button); + g_signal_connect (button, "notify::active", G_CALLBACK (toggle_cycle), warning); gtk_widget_realize (window); g_object_unref (builder); diff --git a/demos/gtk-demo/themes.ui b/demos/gtk-demo/themes.ui index ad0e98fec1..f40d9a46a1 100644 --- a/demos/gtk-demo/themes.ui +++ b/demos/gtk-demo/themes.ui @@ -1,5 +1,14 @@ + + window + 1 + 1 + ok-cancel + warning + Warning + This demo involves rapidly flashing changes and may be hazardous to photosensitive viewers. + 0 From 230107cd84f4a086788bad10fc53be170d493564 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 16:46:38 -0400 Subject: [PATCH 5/9] gtk-demo: Cosmetic improvements to the expander demo Set the textview up like our other readonly textviews. Also sneak in a little easter egg. --- demos/gtk-demo/expander.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/demos/gtk-demo/expander.c b/demos/gtk-demo/expander.c index d5dcd12cc6..16a6029946 100644 --- a/demos/gtk-demo/expander.c +++ b/demos/gtk-demo/expander.c @@ -35,6 +35,10 @@ do_expander (GtkWidget *do_widget) GtkWidget *sw; GtkWidget *tv; GtkTextBuffer *buffer; + GtkTextIter start; + GtkTextIter end; + GtkTextTag *tag; + GdkPaintable *paintable; if (!window) { @@ -64,12 +68,25 @@ do_expander (GtkWidget *do_widget) GTK_POLICY_NEVER, GTK_POLICY_AUTOMATIC); gtk_scrolled_window_set_propagate_natural_height (GTK_SCROLLED_WINDOW (sw), TRUE); + gtk_widget_set_vexpand (sw, TRUE); tv = gtk_text_view_new (); + + g_object_set (tv, + "left-margin", 10, + "right-margin", 10, + "top-margin", 10, + "bottom-margin", 10, + NULL); + buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (tv)); gtk_text_view_set_editable (GTK_TEXT_VIEW (tv), FALSE); + gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (tv), FALSE); gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (tv), GTK_WRAP_WORD); - gtk_text_buffer_set_text (GTK_TEXT_BUFFER (buffer), + gtk_text_view_set_pixels_above_lines (GTK_TEXT_VIEW (tv), 2); + gtk_text_view_set_pixels_below_lines (GTK_TEXT_VIEW (tv), 2); + + gtk_text_buffer_set_text (buffer, "Finally, the full story with all details. " "And all the inside information, including " "error codes, etc etc. Pages of information, " @@ -77,7 +94,22 @@ do_expander (GtkWidget *do_widget) "or even resize the window - it works !\n" "A second paragraph will contain even more " "innuendo, just to make you scroll down or " - "resize the window. Do it already !", -1); + "resize the window.\n" + "Do it already!\n", -1); + + gtk_text_buffer_get_end_iter (buffer, &start); + paintable = GDK_PAINTABLE (gdk_texture_new_from_resource ("/cursors/gtk_logo_cursor.png")); + gtk_text_buffer_insert_paintable (buffer, &start, paintable); + g_object_unref (paintable); + gtk_text_iter_backward_char (&start); + + gtk_text_buffer_get_end_iter (buffer, &end); + tag = gtk_text_buffer_create_tag (buffer, NULL, + "pixels-above-lines", 200, + "justification", GTK_JUSTIFY_RIGHT, + NULL); + gtk_text_buffer_apply_tag (buffer, tag, &start, &end); + gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), tv); gtk_expander_set_child (GTK_EXPANDER (expander), sw); gtk_box_append (GTK_BOX (area), expander); From 42902085e59962aafba7554ed43845e771b945de Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 17:36:41 -0400 Subject: [PATCH 6/9] gtk-demo: Dark theme support for dnd demo Add minimal dark theme support to the dnd demo, by picking suitable default colors for our items. --- demos/gtk-demo/dnd.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/demos/gtk-demo/dnd.c b/demos/gtk-demo/dnd.c index 70ea875c1c..1aff3b1bcd 100644 --- a/demos/gtk-demo/dnd.c +++ b/demos/gtk-demo/dnd.c @@ -153,6 +153,30 @@ click_done (GtkGesture *gesture) gtk_widget_insert_after (item, canvas, last_child); } +static gboolean +theme_is_dark (void) +{ + GtkSettings *settings; + char *theme; + gboolean prefer_dark; + gboolean dark; + + settings = gtk_settings_get_default (); + g_object_get (settings, + "gtk-theme-name", &theme, + "gtk-application-prefer-dark-theme", &prefer_dark, + NULL); + + if ((strcmp (theme, "Adwaita") == 0 && prefer_dark) || strcmp (theme, "HighContrastInverse") == 0) + dark = TRUE; + else + dark = FALSE; + + g_free (theme); + + return dark; +} + static void canvas_item_init (CanvasItem *item) { @@ -180,7 +204,11 @@ canvas_item_init (CanvasItem *item) gtk_widget_set_name (item->label, id); g_free (id); - gdk_rgba_parse (&rgba, "yellow"); + if (theme_is_dark ()) + gdk_rgba_parse (&rgba, "blue"); + else + gdk_rgba_parse (&rgba, "yellow"); + set_color (item, &rgba); item->angle = 0; From 2335953c5d27a525179b23001cd8188e40d34539 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 18:02:04 -0400 Subject: [PATCH 7/9] gtk-demo: Cosmetic fixes for the fontrendering demo Make this look a bit less thrown together. --- demos/gtk-demo/fontrendering.c | 2 +- demos/gtk-demo/fontrendering.ui | 339 ++++++++++++++++---------------- 2 files changed, 172 insertions(+), 169 deletions(-) diff --git a/demos/gtk-demo/fontrendering.c b/demos/gtk-demo/fontrendering.c index d6c3525604..44a628e786 100644 --- a/demos/gtk-demo/fontrendering.c +++ b/demos/gtk-demo/fontrendering.c @@ -19,7 +19,7 @@ static GtkWidget *show_extents = NULL; static PangoContext *context; -static int scale = 10; +static int scale = 9; static void update_image (void) diff --git a/demos/gtk-demo/fontrendering.ui b/demos/gtk-demo/fontrendering.ui index aa9cec3438..e9fcea53d5 100644 --- a/demos/gtk-demo/fontrendering.ui +++ b/demos/gtk-demo/fontrendering.ui @@ -6,164 +6,11 @@ 4 - 600 - 300 - Font rendering - - - 10 - 10 - 10 - - - 10 - Text - 1 - - - - - - Fonts render - - 1 - - - - - - 10 - Font - 1 - - - 0 - 1 - - - - - - - 1 - 1 - - - - - - Hinting - 1 - - - 2 - - - - - - 0 - center - - None - Slight - Medium - Full - - - 3 - - - - - - - - Hint Metrics - - - - - 3 - 1 - - - - - - 1 - - - Show Extents - - - - - 4 - 0 - - - - - - 1 - - - Show Grid - - - - - 4 - 1 - - - - - - list-add-symbolic - - - 5 - 0 - - - - - - list-remove-symbolic - - - 5 - 1 - - - - - - 1 - - 6 - - - - + 1080 + 430 + + + center center @@ -183,11 +30,172 @@ text_radio - - 0 - 3 - 7 - + + + + + + + vertical + + + center + 10 + 10 + 10 + 10 + + + 10 + Text + 1 + + + 1 + + + + + + Fonts render + + 2 + + + + + + 10 + Font + 1 + + + 1 + 1 + + + + + + + 2 + 1 + + + + + + Hinting + 1 + + + 3 + + + + + + 0 + center + + None + Slight + Medium + Full + + + 4 + + + + + + + + Hint Metrics + + + + + 4 + 1 + + + + + + 1 + + + Show Extents + + + + + 5 + 0 + + + + + + 1 + + + Show Grid + + + + + 5 + 1 + + + + + + list-add-symbolic + + + 6 + 0 + + + + + + list-remove-symbolic + + + 6 + 1 + + + + + + 1 + + 7 + + + @@ -203,11 +211,6 @@ 0 - - 0 - 4 - 7 - From da0955feeb6bc80d77d29bf74684c94bd76ef581 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 18:05:27 -0400 Subject: [PATCH 8/9] gtk-demo: Cosmetic fixes to the textmask demo Make this come up with the right size. --- demos/gtk-demo/textmask.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demos/gtk-demo/textmask.c b/demos/gtk-demo/textmask.c index 2869304704..60a81dc270 100644 --- a/demos/gtk-demo/textmask.c +++ b/demos/gtk-demo/textmask.c @@ -61,7 +61,7 @@ do_textmask (GtkWidget *do_widget) { window = gtk_window_new (); gtk_window_set_resizable (GTK_WINDOW (window), TRUE); - gtk_widget_set_size_request (window, 400, 200); + gtk_widget_set_size_request (window, 400, 240); gtk_window_set_title (GTK_WINDOW (window), "Text Mask"); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); From e5247b7cbb03e73dfbea4942fefbeef5ccda37e0 Mon Sep 17 00:00:00 2001 From: Matthias Clasen Date: Sun, 9 Aug 2020 18:27:18 -0400 Subject: [PATCH 9/9] gtk-demo: Finish peg solitaire demo The restart button was simply not implemented. While we are at it, make the pegs a bit bigger, so clicking them is easier. --- demos/gtk-demo/peg_solitaire.c | 162 +++++++++++++++++++-------------- 1 file changed, 96 insertions(+), 66 deletions(-) diff --git a/demos/gtk-demo/peg_solitaire.c b/demos/gtk-demo/peg_solitaire.c index 6532cce254..81f9a5c4c5 100644 --- a/demos/gtk-demo/peg_solitaire.c +++ b/demos/gtk-demo/peg_solitaire.c @@ -6,8 +6,6 @@ #include -static GtkWidget *window = NULL; - /* Create an object for the pegs that get moved around in the game. * * We implement the GdkPaintable interface for them, so we can use GtkPicture @@ -56,11 +54,25 @@ solitaire_peg_get_flags (GdkPaintable *paintable) return GDK_PAINTABLE_STATIC_CONTENTS | GDK_PAINTABLE_STATIC_SIZE; } +static int +solitaire_peg_get_intrinsic_width (GdkPaintable *paintable) +{ + return 32; +} + +static int +solitaire_peg_get_intrinsic_height (GdkPaintable *paintable) +{ + return 32; +} + static void solitaire_peg_paintable_init (GdkPaintableInterface *iface) { iface->snapshot = solitaire_peg_snapshot; iface->get_flags = solitaire_peg_get_flags; + iface->get_intrinsic_width = solitaire_peg_get_intrinsic_width; + iface->get_intrinsic_height = solitaire_peg_get_intrinsic_height; } /* When defining the GType, we need to implement the GdkPaintable interface */ @@ -259,25 +271,99 @@ drop_drop (GtkDropTarget *target, return TRUE; } +static void +create_board (GtkWidget *window) +{ + GtkWidget *grid; + GtkWidget *image; + int x, y; + GtkDragSource *source; + GtkDropTarget *target; + + grid = gtk_grid_new (); + gtk_widget_set_halign (grid, GTK_ALIGN_CENTER); + gtk_widget_set_valign (grid, GTK_ALIGN_CENTER); + gtk_grid_set_row_spacing (GTK_GRID (grid), 6); + gtk_grid_set_column_spacing (GTK_GRID (grid), 6); + gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE); + gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE); + gtk_window_set_child (GTK_WINDOW (window), grid); + + for (x = 0; x < 7; x++) + { + for (y = 0; y < 7; y++) + { + if ((x < 2 || x >= 5) && (y < 2 || y >= 5)) + continue; + + image = gtk_image_new (); + gtk_image_set_icon_size (GTK_IMAGE (image), GTK_ICON_SIZE_LARGE); + if (x != 3 || y != 3) + { + SolitairePeg *peg = solitaire_peg_new (); + solitaire_peg_set_position (peg, x, y); + gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (peg)); + } + + gtk_grid_attach (GTK_GRID (grid), image, x, y, 1, 1); + + /* Set up the drag source. + * This is rather straightforward: Set the supported actions + * (in our case, pegs can only be moved) and connect all the + * relevant signals. + * And because all drag'n'drop handling is done via event controllers, + * we need to add the controller to the widget. + */ + source = gtk_drag_source_new (); + gtk_drag_source_set_actions (source, GDK_ACTION_MOVE); + g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), image); + g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image); + g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), image); + gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source)); + + /* Set up the drop target. + * This is more involved, because the game logic goes here. + */ + + /* First we specify the data we accept: pegs. + * And we only want moves. + */ + target = gtk_drop_target_new (SOLITAIRE_TYPE_PEG, GDK_ACTION_MOVE); + /* Then we connect our signals. + */ + g_signal_connect (target, "accept", G_CALLBACK (drop_accept), image); + g_signal_connect (target, "drop", G_CALLBACK (drop_drop), image); + /* Finally, like above, we add it to the widget. + */ + gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (target)); + } + } +} + +static void +restart_game (GtkButton *button, + GtkWidget *window) +{ + create_board (window); +} + GtkWidget * do_peg_solitaire (GtkWidget *do_widget) { + static GtkWidget *window = NULL; + if (!window) { GtkWidget *header; GtkWidget *restart; - GtkWidget *grid; - GtkWidget *image; - int x, y; - GtkDragSource *source; - GtkDropTarget *target; + + window = gtk_window_new (); restart = gtk_button_new_from_icon_name ("view-refresh-symbolic"); - g_signal_connect (restart, "clicked", G_CALLBACK (restart), NULL); + g_signal_connect (restart, "clicked", G_CALLBACK (restart_game), window); header = gtk_header_bar_new (); gtk_header_bar_pack_start (GTK_HEADER_BAR (header), restart); - window = gtk_window_new (); gtk_window_set_display (GTK_WINDOW (window), gtk_widget_get_display (do_widget)); gtk_window_set_title (GTK_WINDOW (window), "Peg Solitaire"); @@ -285,63 +371,7 @@ do_peg_solitaire (GtkWidget *do_widget) gtk_window_set_default_size (GTK_WINDOW (window), 400, 300); g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window); - grid = gtk_grid_new (); - gtk_widget_set_halign (grid, GTK_ALIGN_CENTER); - gtk_widget_set_valign (grid, GTK_ALIGN_CENTER); - gtk_grid_set_row_spacing (GTK_GRID (grid), 6); - gtk_grid_set_column_spacing (GTK_GRID (grid), 6); - gtk_grid_set_row_homogeneous (GTK_GRID (grid), TRUE); - gtk_grid_set_column_homogeneous (GTK_GRID (grid), TRUE); - gtk_window_set_child (GTK_WINDOW (window), grid); - - for (x = 0; x < 7; x++) - { - for (y = 0; y < 7; y++) - { - if ((x < 2 || x >= 5) && (y < 2 || y >= 5)) - continue; - - image = gtk_image_new (); - if (x != 3 || y != 3) - { - SolitairePeg *peg = solitaire_peg_new (); - solitaire_peg_set_position (peg, x, y); - gtk_image_set_from_paintable (GTK_IMAGE (image), GDK_PAINTABLE (peg)); - } - - gtk_grid_attach (GTK_GRID (grid), image, x, y, 1, 1); - - /* Set up the drag source. - * This is rather straightforward: Set the supported actions - * (in our case, pegs can only be moved) and connect all the - * relevant signals. - * And because all drag'n'drop handling is done via event controllers, - * we need to add the controller to the widget. - */ - source = gtk_drag_source_new (); - gtk_drag_source_set_actions (source, GDK_ACTION_MOVE); - g_signal_connect (source, "prepare", G_CALLBACK (drag_prepare), image); - g_signal_connect (source, "drag-begin", G_CALLBACK (drag_begin), image); - g_signal_connect (source, "drag-end", G_CALLBACK (drag_end), image); - gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (source)); - - /* Set up the drop target. - * This is more involved, because the game logic goes here. - */ - - /* First we specify the data we accept: pegs. - * And we only want moves. - */ - target = gtk_drop_target_new (SOLITAIRE_TYPE_PEG, GDK_ACTION_MOVE); - /* Then we connect our signals. - */ - g_signal_connect (target, "accept", G_CALLBACK (drop_accept), image); - g_signal_connect (target, "drop", G_CALLBACK (drop_drop), image); - /* Finally, like above, we add it to the widget. - */ - gtk_widget_add_controller (image, GTK_EVENT_CONTROLLER (target)); - } - } + create_board (window); } if (!gtk_widget_get_visible (window))