1#include <string.h>
2#include <gtk/gtk.h>
3
4static const char *css =
5".overlay-green {"
6" background-image: none;"
7" background-color: green;"
8"}\n"
9".overlay-white {"
10" background-image: none;"
11" background-color: white;"
12"}\n"
13".transparent-red {"
14" background-image: none;"
15" background-color: rgba(255, 0, 0, 0.8);"
16"}\n"
17".transparent-green {"
18" background-image: none;"
19" background-color: rgba(0, 255, 0, 0.8);"
20"}\n"
21".transparent-blue {"
22" background-image: none;"
23" background-color: rgba(0, 0, 255, 0.8);"
24"}\n"
25".transparent-purple {"
26" background-image: none;"
27" background-color: rgba(255, 0, 255, 0.8);"
28"}\n"
29;
30
31
32/* test that margins and non-zero allocation x/y
33 * of the main widget are handled correctly
34 */
35static GtkWidget *
36test_nonzerox (void)
37{
38 GtkWidget *win;
39 GtkWidget *grid;
40 GtkWidget *overlay;
41 GtkWidget *text;
42 GtkWidget *child;
43
44 win = gtk_window_new ();
45 gtk_window_set_title (GTK_WINDOW (win), title: "Non-zero X");
46
47 grid = gtk_grid_new ();
48 gtk_widget_set_margin_start (widget: grid, margin: 5);
49 gtk_widget_set_margin_end (widget: grid, margin: 5);
50 gtk_widget_set_margin_top (widget: grid, margin: 5);
51 gtk_widget_set_margin_bottom (widget: grid, margin: 5);
52
53 gtk_window_set_child (GTK_WINDOW (win), child: grid);
54 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Above"), column: 1, row: 0, width: 1, height: 1);
55 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Below"), column: 1, row: 2, width: 1, height: 1);
56 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Left"), column: 0, row: 1, width: 1, height: 1);
57 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Right"), column: 2, row: 1, width: 1, height: 1);
58
59 overlay = gtk_overlay_new ();
60 gtk_grid_attach (GTK_GRID (grid), child: overlay, column: 1, row: 1, width: 1, height: 1);
61
62 text = gtk_text_view_new ();
63 gtk_widget_set_size_request (widget: text, width: 200, height: 200);
64 gtk_widget_set_hexpand (widget: text, TRUE);
65 gtk_widget_set_vexpand (widget: text, TRUE);
66 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: text);
67
68 child = gtk_label_new (str: "I'm the overlay");
69 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_START);
70 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_START);
71 gtk_widget_set_margin_start (widget: child, margin: 3);
72 gtk_widget_set_margin_end (widget: child, margin: 3);
73 gtk_widget_set_margin_top (widget: child, margin: 3);
74 gtk_widget_set_margin_bottom (widget: child, margin: 3);
75
76 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
77
78 child = gtk_label_new (str: "No, I'm the overlay");
79 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_END);
80 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_END);
81 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
82 gtk_widget_set_margin_start (widget: child, margin: 3);
83 gtk_widget_set_margin_end (widget: child, margin: 3);
84 gtk_widget_set_margin_top (widget: child, margin: 3);
85 gtk_widget_set_margin_bottom (widget: child, margin: 3);
86
87 return win;
88}
89
90static gboolean
91get_child_position (GtkOverlay *overlay,
92 GtkWidget *widget,
93 GtkAllocation *alloc,
94 GtkWidget *relative)
95{
96 GtkRequisition req;
97 GtkWidget *child;
98 GtkAllocation main_alloc;
99 double x, y;
100
101 child = gtk_overlay_get_child (GTK_OVERLAY (overlay));
102
103 gtk_widget_translate_coordinates (src_widget: relative, dest_widget: child, src_x: 0, src_y: 0, dest_x: &x, dest_y: &y);
104 main_alloc.x = x;
105 main_alloc.y = y;
106 main_alloc.width = gtk_widget_get_allocated_width (widget: relative);
107 main_alloc.height = gtk_widget_get_allocated_height (widget: relative);
108
109 gtk_widget_get_preferred_size (widget, NULL, natural_size: &req);
110
111 alloc->x = main_alloc.x;
112 alloc->width = MIN (main_alloc.width, req.width);
113 if (gtk_widget_get_halign (widget) == GTK_ALIGN_END)
114 alloc->x += main_alloc.width - req.width;
115
116 alloc->y = main_alloc.y;
117 alloc->height = MIN (main_alloc.height, req.height);
118 if (gtk_widget_get_valign (widget) == GTK_ALIGN_END)
119 alloc->y += main_alloc.height - req.height;
120
121 return TRUE;
122}
123
124/* test custom positioning */
125static GtkWidget *
126test_relative (void)
127{
128 GtkWidget *win;
129 GtkWidget *grid;
130 GtkWidget *overlay;
131 GtkWidget *text;
132 GtkWidget *child;
133
134 win = gtk_window_new ();
135 gtk_window_set_title (GTK_WINDOW (win), title: "Custom positioning");
136
137 overlay = gtk_overlay_new ();
138 gtk_window_set_child (GTK_WINDOW (win), child: overlay);
139
140 grid = gtk_grid_new ();
141 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: grid);
142 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Above"), column: 1, row: 0, width: 1, height: 1);
143 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Below"), column: 1, row: 2, width: 1, height: 1);
144 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Left"), column: 0, row: 1, width: 1, height: 1);
145 gtk_grid_attach (GTK_GRID (grid), child: gtk_label_new (str: "Right"), column: 2, row: 1, width: 1, height: 1);
146
147 text = gtk_text_view_new ();
148 gtk_widget_set_size_request (widget: text, width: 200, height: 200);
149 gtk_widget_set_margin_start (widget: text, margin: 5);
150 gtk_widget_set_margin_end (widget: text, margin: 5);
151 gtk_widget_set_margin_top (widget: text, margin: 5);
152 gtk_widget_set_margin_bottom (widget: text, margin: 5);
153 gtk_widget_set_hexpand (widget: text, TRUE);
154 gtk_widget_set_vexpand (widget: text, TRUE);
155 gtk_grid_attach (GTK_GRID (grid), child: text, column: 1, row: 1, width: 1, height: 1);
156 g_signal_connect (overlay, "get-child-position",
157 G_CALLBACK (get_child_position), text);
158
159 child = gtk_label_new (str: "Top left overlay");
160 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_START);
161 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_START);
162 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
163 gtk_widget_set_margin_start (widget: child, margin: 1);
164 gtk_widget_set_margin_end (widget: child, margin: 1);
165 gtk_widget_set_margin_top (widget: child, margin: 1);
166 gtk_widget_set_margin_bottom (widget: child, margin: 1);
167
168 child = gtk_label_new (str: "Bottom right overlay");
169 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_END);
170 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_END);
171 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
172 gtk_widget_set_margin_start (widget: child, margin: 1);
173 gtk_widget_set_margin_end (widget: child, margin: 1);
174 gtk_widget_set_margin_top (widget: child, margin: 1);
175 gtk_widget_set_margin_bottom (widget: child, margin: 1);
176
177 return win;
178}
179
180/* test GTK_ALIGN_FILL handling */
181static GtkWidget *
182test_fullwidth (void)
183{
184 GtkWidget *win;
185 GtkWidget *overlay;
186 GtkWidget *text;
187 GtkWidget *child;
188
189 win = gtk_window_new ();
190 gtk_window_set_title (GTK_WINDOW (win), title: "Full-width");
191
192 overlay = gtk_overlay_new ();
193 gtk_window_set_child (GTK_WINDOW (win), child: overlay);
194
195 text = gtk_text_view_new ();
196 gtk_widget_set_size_request (widget: text, width: 200, height: 200);
197 gtk_widget_set_hexpand (widget: text, TRUE);
198 gtk_widget_set_vexpand (widget: text, TRUE);
199 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: text);
200
201 child = gtk_label_new (str: "Fullwidth top overlay");
202 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_FILL);
203 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_START);
204 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
205 gtk_widget_set_margin_start (widget: child, margin: 4);
206 gtk_widget_set_margin_end (widget: child, margin: 4);
207 gtk_widget_set_margin_top (widget: child, margin: 4);
208 gtk_widget_set_margin_bottom (widget: child, margin: 4);
209
210 return win;
211}
212
213/* test that scrolling works as expected */
214static GtkWidget *
215test_scrolling (void)
216{
217 GtkWidget *win;
218 GtkWidget *overlay;
219 GtkWidget *sw;
220 GtkWidget *text;
221 GtkWidget *child;
222 GtkTextBuffer *buffer;
223 char *contents;
224 gsize len;
225
226 win = gtk_window_new ();
227 gtk_window_set_title (GTK_WINDOW (win), title: "Scrolling");
228
229 overlay = gtk_overlay_new ();
230 gtk_window_set_child (GTK_WINDOW (win), child: overlay);
231
232 sw = gtk_scrolled_window_new ();
233 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (sw), width: 200);
234 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), height: 200);
235 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: sw);
236
237 text = gtk_text_view_new ();
238 buffer = gtk_text_buffer_new (NULL);
239 if (!g_file_get_contents (filename: "testoverlay.c", contents: &contents, length: &len, NULL))
240 {
241 contents = g_strdup (str: "Text should go here...");
242 len = strlen (s: contents);
243 }
244 gtk_text_buffer_set_text (buffer, text: contents, len);
245 g_free (mem: contents);
246 gtk_text_view_set_buffer (GTK_TEXT_VIEW (text), buffer);
247
248 gtk_widget_set_hexpand (widget: text, TRUE);
249 gtk_widget_set_vexpand (widget: text, TRUE);
250 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: text);
251
252 child = gtk_label_new (str: "This should be visible");
253 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_CENTER);
254 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_END);
255 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
256 gtk_widget_set_margin_start (widget: child, margin: 4);
257 gtk_widget_set_margin_end (widget: child, margin: 4);
258 gtk_widget_set_margin_top (widget: child, margin: 4);
259 gtk_widget_set_margin_bottom (widget: child, margin: 4);
260
261 return win;
262}
263
264static const char *buffer =
265"<interface>"
266" <object class='GtkWindow' id='window'>"
267" <property name='title'>GtkBuilder support</property>"
268" <child>"
269" <object class='GtkOverlay' id='overlay'>"
270" <child type='overlay'>"
271" <object class='GtkLabel' id='overlay-child'>"
272" <property name='label'>Witty remark goes here</property>"
273" <property name='halign'>end</property>"
274" <property name='valign'>end</property>"
275" <property name='margin-top'>4</property>"
276" <property name='margin-bottom'>4</property>"
277" <property name='margin-start'>4</property>"
278" <property name='margin-end'>4</property>"
279" </object>"
280" </child>"
281" <child>"
282" <object class='GtkGrid' id='grid'>"
283" <child>"
284" <object class='GtkLabel' id='left'>"
285" <property name='label'>Left</property>"
286" <layout>"
287" <property name='column'>0</property>"
288" <property name='row'>0</property>"
289" </layout>"
290" </object>"
291" </child>"
292" <child>"
293" <object class='GtkLabel' id='right'>"
294" <property name='label'>Right</property>"
295" <layout>"
296" <property name='column'>2</property>"
297" <property name='row'>0</property>"
298" </layout>"
299" </object>"
300" </child>"
301" <child>"
302" <object class='GtkTextView' id='text'>"
303" <property name='width-request'>200</property>"
304" <property name='height-request'>200</property>"
305" <property name='hexpand'>True</property>"
306" <property name='vexpand'>True</property>"
307" <layout>"
308" <property name='column'>1</property>"
309" <property name='row'>0</property>"
310" </layout>"
311" </object>"
312" </child>"
313" </object>"
314" </child>"
315" </object>"
316" </child>"
317" </object>"
318"</interface>";
319
320/* test that overlays can be constructed with GtkBuilder */
321static GtkWidget *
322test_builder (void)
323{
324 GtkBuilder *builder;
325 GtkWidget *win;
326 GError *error;
327
328 builder = gtk_builder_new ();
329
330 error = NULL;
331 if (!gtk_builder_add_from_string (builder, buffer, length: -1, error: &error))
332 {
333 g_warning ("%s", error->message);
334 g_error_free (error);
335 return NULL;
336 }
337
338 win = (GtkWidget *)gtk_builder_get_object (builder, name: "window");
339 g_object_ref (win);
340
341 g_object_unref (object: builder);
342
343 return win;
344}
345
346static void
347on_enter (GtkEventController *controller,
348 double x,
349 double y,
350 GtkWidget *overlay)
351{
352 GtkWidget *child = gtk_event_controller_get_widget (controller);
353
354 if (gtk_widget_get_halign (widget: child) == GTK_ALIGN_START)
355 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_END);
356 else
357 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_START);
358
359 gtk_widget_queue_resize (widget: overlay);
360}
361
362static GtkWidget *
363test_chase (void)
364{
365 GtkWidget *win;
366 GtkWidget *overlay;
367 GtkWidget *sw;
368 GtkWidget *text;
369 GtkWidget *child;
370 GtkTextBuffer *text_buffer;
371 char *contents;
372 gsize len;
373 GtkEventController *controller;
374
375 win = gtk_window_new ();
376 gtk_window_set_title (GTK_WINDOW (win), title: "Chase");
377
378 overlay = gtk_overlay_new ();
379 gtk_window_set_child (GTK_WINDOW (win), child: overlay);
380
381 sw = gtk_scrolled_window_new ();
382 gtk_scrolled_window_set_min_content_width (GTK_SCROLLED_WINDOW (sw), width: 200);
383 gtk_scrolled_window_set_min_content_height (GTK_SCROLLED_WINDOW (sw), height: 200);
384 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: sw);
385
386 text = gtk_text_view_new ();
387 text_buffer = gtk_text_buffer_new (NULL);
388 if (!g_file_get_contents (filename: "testoverlay.c", contents: &contents, length: &len, NULL))
389 {
390 contents = g_strdup (str: "Text should go here...");
391 len = strlen (s: contents);
392 }
393 gtk_text_buffer_set_text (buffer: text_buffer, text: contents, len);
394 g_free (mem: contents);
395 gtk_text_view_set_buffer (GTK_TEXT_VIEW (text), buffer: text_buffer);
396
397 gtk_widget_set_hexpand (widget: text, TRUE);
398 gtk_widget_set_vexpand (widget: text, TRUE);
399 gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), child: text);
400
401 child = gtk_label_new (str: "Try to enter");
402 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_START);
403 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_END);
404 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
405 gtk_widget_set_margin_start (widget: child, margin: 4);
406 gtk_widget_set_margin_end (widget: child, margin: 4);
407 gtk_widget_set_margin_top (widget: child, margin: 4);
408 gtk_widget_set_margin_bottom (widget: child, margin: 4);
409
410 controller = gtk_event_controller_motion_new ();
411 g_signal_connect (controller, "enter", G_CALLBACK (on_enter), overlay);
412 gtk_widget_add_controller (widget: child, controller);
413
414 return win;
415}
416
417static GtkWidget *
418test_stacking (void)
419{
420 GtkWidget *win;
421 GtkWidget *overlay;
422 GtkWidget *main_child;
423 GtkWidget *label;
424 GtkWidget *child;
425 GtkWidget *grid;
426 GtkWidget *check1;
427 GtkWidget *check2;
428
429 win = gtk_window_new ();
430 gtk_window_set_title (GTK_WINDOW (win), title: "Stacking");
431
432 grid = gtk_grid_new ();
433 overlay = gtk_overlay_new ();
434 main_child = gtk_box_new (orientation: GTK_ORIENTATION_HORIZONTAL, spacing: 0);
435 gtk_widget_add_css_class (widget: main_child, css_class: "overlay-green");
436 gtk_widget_set_hexpand (widget: main_child, TRUE);
437 gtk_widget_set_vexpand (widget: main_child, TRUE);
438 label = gtk_label_new (str: "Main child");
439 child = gtk_label_new (str: "Overlay");
440 gtk_widget_set_halign (widget: child, align: GTK_ALIGN_END);
441 gtk_widget_set_valign (widget: child, align: GTK_ALIGN_END);
442
443 check1 = gtk_check_button_new_with_label (label: "Show main");
444 g_object_bind_property (source: main_child, source_property: "visible", target: check1, target_property: "active", flags: G_BINDING_BIDIRECTIONAL);
445
446 check2 = gtk_check_button_new_with_label (label: "Show overlay");
447 g_object_bind_property (source: child, source_property: "visible", target: check2, target_property: "active", flags: G_BINDING_BIDIRECTIONAL);
448 gtk_box_append (GTK_BOX (main_child), child: label);
449 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: main_child);
450 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: child);
451 gtk_grid_attach (GTK_GRID (grid), child: overlay, column: 1, row: 0, width: 1, height: 3);
452 gtk_window_set_child (GTK_WINDOW (win), child: grid);
453
454 gtk_grid_attach (GTK_GRID (grid), child: check1, column: 0, row: 0, width: 1, height: 1);
455 gtk_grid_attach (GTK_GRID (grid), child: check2, column: 0, row: 1, width: 1, height: 1);
456 child = gtk_label_new (str: "");
457 gtk_widget_set_vexpand (widget: child, TRUE);
458 gtk_grid_attach (GTK_GRID (grid), child, column: 0, row: 2, width: 1, height: 1);
459
460 return win;
461}
462
463static GtkWidget *
464test_input_stacking (void)
465{
466 GtkWidget *win;
467 GtkWidget *overlay;
468 GtkWidget *label, *entry;
469 GtkWidget *grid;
470 GtkWidget *button;
471 GtkWidget *vbox;
472 int i,j;
473
474 win = gtk_window_new ();
475 gtk_window_set_title (GTK_WINDOW (win), title: "Input Stacking");
476
477 overlay = gtk_overlay_new ();
478 grid = gtk_grid_new ();
479 gtk_overlay_set_child (GTK_OVERLAY (overlay), child: grid);
480
481 for (j = 0; j < 5; j++)
482 {
483 for (i = 0; i < 5; i++)
484 {
485 button = gtk_button_new_with_label (label: " ");
486 gtk_widget_set_hexpand (widget: button, TRUE);
487 gtk_widget_set_vexpand (widget: button, TRUE);
488 gtk_grid_attach (GTK_GRID (grid), child: button, column: i, row: j, width: 1, height: 1);
489 }
490 }
491
492 vbox = gtk_box_new (orientation: GTK_ORIENTATION_VERTICAL, spacing: 10);
493 gtk_overlay_add_overlay (GTK_OVERLAY (overlay), widget: vbox);
494 gtk_widget_set_can_target (widget: vbox, FALSE);
495 gtk_widget_set_halign (widget: vbox, align: GTK_ALIGN_CENTER);
496 gtk_widget_set_valign (widget: vbox, align: GTK_ALIGN_CENTER);
497
498 label = gtk_label_new (str: "This is some overlaid text\n"
499 "It does not get input\n"
500 "But the entry does");
501 gtk_widget_set_margin_top (widget: label, margin: 8);
502 gtk_widget_set_margin_bottom (widget: label, margin: 8);
503 gtk_box_append (GTK_BOX (vbox), child: label);
504
505 entry = gtk_entry_new ();
506 gtk_widget_set_margin_top (widget: entry, margin: 8);
507 gtk_widget_set_margin_bottom (widget: entry, margin: 8);
508 gtk_box_append (GTK_BOX (vbox), child: entry);
509
510
511 gtk_window_set_child (GTK_WINDOW (win), child: overlay);
512
513 return win;
514}
515
516int
517main (int argc, char *argv[])
518{
519 GtkWidget *win1;
520 GtkWidget *win2;
521 GtkWidget *win3;
522 GtkWidget *win4;
523 GtkWidget *win5;
524 GtkWidget *win6;
525 GtkWidget *win7;
526 GtkWidget *win8;
527 GtkCssProvider *css_provider;
528
529 gtk_init ();
530
531 if (g_getenv (variable: "RTL"))
532 gtk_widget_set_default_direction (dir: GTK_TEXT_DIR_RTL);
533
534 css_provider = gtk_css_provider_new ();
535 gtk_css_provider_load_from_data (css_provider, data: css, length: -1);
536 gtk_style_context_add_provider_for_display (display: gdk_display_get_default (),
537 GTK_STYLE_PROVIDER (css_provider),
538 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
539
540 win1 = test_nonzerox ();
541 gtk_widget_show (widget: win1);
542
543 win2 = test_relative ();
544 gtk_widget_show (widget: win2);
545
546 win3 = test_fullwidth ();
547 gtk_widget_show (widget: win3);
548
549 win4 = test_scrolling ();
550 gtk_widget_show (widget: win4);
551
552 win5 = test_builder ();
553 gtk_widget_show (widget: win5);
554
555 win6 = test_chase ();
556 gtk_widget_show (widget: win6);
557
558 win7 = test_stacking ();
559 gtk_widget_show (widget: win7);
560
561 win8 = test_input_stacking ();
562 gtk_widget_show (widget: win8);
563
564 while (TRUE)
565 g_main_context_iteration (NULL, TRUE);
566
567 return 0;
568}
569

Provided by KDAB

Privacy Policy

source code of gtk/tests/testoverlay.c