Freeciv-3.3: /fast/freeciv/nightly/main/client/gui-gtk-4.0/gui_main.c Source File

Freeciv-3.3

Loading...
Searching...
No Matches
gui_main.c
Go to the documentation of this file.
1/***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12***********************************************************************/
13
14#ifdef HAVE_CONFIG_H
15#include <fc_config.h>
16#endif
17
18#ifdef AUDIO_SDL
19/* Though it would happily compile without this include,
20 * it is needed for sound to work.
21 * It defines "main" macro to rename our main() so that
22 * it can install SDL's own. */
23#ifdef SDL2_PLAIN_INCLUDE
24#include <SDL.h>
25#else /* PLAIN_INCLUDE */
26#include <SDL2/SDL.h>
27#endif /* PLAIN_INCLUDE */
28#endif /* AUDIO_SDL */
29
30#ifdef HAVE_LOCALE_H
31#include <locale.h>
32#endif
33#include <stdarg.h>
34#include <stdio.h>
35#include <stdlib.h>
36#include <string.h>
37#include <time.h>
38
39#ifdef HAVE_UNISTD_H
40#include <unistd.h>
41#endif
42
43#include <gtk/gtk.h>
44#include <gdk/gdkkeysyms.h>
45
46/* utility */
47#include "fc_cmdline.h"
48#include "fciconv.h"
49#include "fcintl.h"
50#include "log.h"
51#include "mem.h"
52#include "support.h"
53
54/* common */
55#include "dataio.h"
56#include "featured_text.h"
57#include "game.h"
58#include "government.h"
59#include "map.h"
60#include "unitlist.h"
61#include "version.h"
62
63/* client */
64#include "audio.h"
65#include "client_main.h"
66#include "climisc.h"
67#include "clinet.h"
68#include "colors.h"
69#include "connectdlg_common.h"
70#include "control.h"
71#include "editor.h"
72#include "options.h"
73#include "text.h"
74#include "tilespec.h"
75#include "zoom.h"
76
77/* client/gui-gtk-4.0 */
78#include "chatline.h"
79#include "citizensinfo.h"
80#include "connectdlg.h"
81#include "cma_fe.h"
82#include "dialogs.h"
83#include "diplodlg.h"
84#include "editgui.h"
85#include "gotodlg.h"
86#include "graphics.h"
87#include "gui_stuff.h"
88#include "happiness.h"
89#include "helpdlg.h"
90#include "inteldlg.h"
91#include "mapctrl.h"
92#include "mapview.h"
93#include "menu.h"
94#include "messagewin.h"
95#include "optiondlg.h"
96#include "pages.h"
97#include "plrdlg.h"
98#include "luaconsole.h"
99#include "spaceshipdlg.h"
100#include "repodlgs.h"
101#include "voteinfo_bar.h"
102
103#include "gui_main.h"
104
105 const char *client_string = GUI_NAME_FULL;
106
107 GtkWidget *map_canvas; /* GtkDrawingArea */
108 GtkWidget *map_horizontal_scrollbar;
109 GtkWidget *map_vertical_scrollbar;
110
111 GtkWidget *overview_canvas; /* GtkDrawingArea */
112 GtkWidget *overview_scrolled_window; /* GtkScrolledWindow */
113/* The two values below define the width and height of the map overview. The
114 * first set of values (2*62, 2*46) define the size for a netbook display. For
115 * bigger displays the values are doubled (default). */
116#define OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK (2 * 64)
117#define OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK (2 * 46)
118#define OVERVIEW_CANVAS_STORE_WIDTH \
119 (2 * OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK)
120#define OVERVIEW_CANVAS_STORE_HEIGHT \
121 (2 * OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK)
122 int overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH;
123 int overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT;
124
125 GtkWidget *toplevel;
126 GtkWidget *toplevel_tabs;
127 GtkWidget *top_vbox;
128 GtkWidget *top_notebook, *bottom_notebook, *right_notebook;
129 GtkWidget *map_widget;
130 static GtkWidget *bottom_hpaned;
131
132 PangoFontDescription *city_names_style = NULL;
133 PangoFontDescription *city_productions_style = NULL;
134 PangoFontDescription *reqtree_text_style = NULL;
135
136 GtkWidget *main_frame_civ_name;
137 GtkWidget *main_label_info;
138
139 GtkWidget *avbox, *ahbox, *conn_box;
140 GtkWidget* scroll_panel;
141
142 GtkWidget *econ_label[10];
143 GtkWidget *bulb_label;
144 GtkWidget *sun_label;
145 GtkWidget *flake_label;
146 GtkWidget *government_label;
147 GtkWidget *timeout_label;
148 GtkWidget *turn_done_button;
149
150 GtkWidget *unit_info_label;
151 GtkWidget *unit_info_box;
152 GtkWidget *unit_info_frame;
153
154 GtkWidget *econ_widget;
155
156 const char *const gui_character_encoding = "UTF-8";
157 const bool gui_use_transliteration = FALSE;
158
159 static GdkPaintable *empty_unit_paintable = NULL;
160 static GtkWidget *unit_pic_table;
161 static GtkWidget *unit_pic;
162 static GtkWidget *unit_below_pic[MAX_NUM_UNITS_BELOW];
163 static GtkWidget *more_arrow;
164 static GtkWidget *more_arrow_container;
165
166 static int unit_id_top;
167 static int unit_ids[MAX_NUM_UNITS_BELOW]; /* ids of the units icons in
168 * information display: (or 0) */
169 GtkTextView *main_message_area;
170 GtkTextBuffer *message_buffer = NULL;
171 static GtkWidget *allied_chat_toggle_button;
172
173 static gint timer_id; /* Ditto */
174 static GIOChannel *srv_channel;
175 static guint srv_id;
176 gint cur_x, cur_y;
177
178 static bool gui_up = FALSE;
179
180 static bool audio_paused = FALSE;
181 static bool client_focus = TRUE;
182
183 static GtkApplication *fc_app;
184
185 static struct video_mode vmode = { -1, -1 };
186
187static void set_g_log_callbacks(void);
188
189static gboolean show_info_popup(GtkGestureClick *gesture, int n_press,
190 double x, double y, gpointer data);
191
192static void end_turn_callback(GtkWidget *w, gpointer data);
193static gboolean get_net_input(GIOChannel *source, GIOCondition condition,
194 gpointer data);
195static void set_wait_for_writable_socket(struct connection *pc,
196 bool socket_writable);
197
198static void print_usage(void);
199static void activate_gui(GtkApplication *app, gpointer data);
200static bool parse_options(int argc, char **argv);
201static gboolean toplevel_key_press_handler(GtkEventControllerKey *controller,
202 guint keyval,
203 guint keycode,
204 GdkModifierType state,
205 gpointer data);
206static gboolean mouse_scroll_mapcanvas(GtkEventControllerScroll *controller,
207 gdouble dx, gdouble dy,
208 gpointer data);
209
210static void tearoff_callback(GtkWidget *b, gpointer data);
211static GtkWidget *detached_widget_new(void);
212static GtkWidget *detached_widget_fill(GtkWidget *tearbox);
213
214static gboolean select_unit_pic_callback(GtkGestureClick *gesture, int n_press,
215 double x, double y, gpointer data);
216static gboolean select_more_arrow_callback(GtkGestureClick *gesture, int n_press,
217 double x, double y, gpointer data);
218static gboolean quit_dialog_callback(void);
219
220static void allied_chat_button_toggled(GtkToggleButton *button,
221 gpointer user_data);
222
223static void free_unit_table(void);
224
225static void adjust_default_options(void);
226
227 static float zoom_steps_custom[] = {
228 -1.0, 0.13, 0.25, 0.5, 0.75, 1.0, 1.25, 1.5, 2.0, 2.5, 3.0, 4.0, -1.0
229};
230
231/**********************************************************************/
234 static void log_callback_utf8(enum log_level level, const char *message,
235 bool file_too)
236{
237 if (!file_too || level <= LOG_FATAL) {
238 fc_fprintf(stderr, "%d: %s\n", level, message);
239 }
240}
241
242/**********************************************************************/
246 static gboolean timer_callback(gpointer data)
247{
248 double seconds = real_timer_callback();
249
250 if (gui_options.silent_when_not_in_focus) {
251 if (!audio_paused && !client_focus) {
252 audio_pause();
253 audio_paused = TRUE;
254 } else if (audio_paused && client_focus) {
255 audio_resume();
256 audio_paused = FALSE;
257 }
258 }
259
260 timer_id = g_timeout_add(seconds * 1000, timer_callback, NULL);
261
262 return FALSE;
263}
264
265/**********************************************************************/
269 static void print_usage(void)
270{
271 /* Add client-specific usage information here */
272 fc_fprintf(stderr,
273 _("gtk4-client gui-specific options are:\n"));
274
275 fc_fprintf(stderr,
276 _("-r, --resolution WIDTHxHEIGHT\tAssume given resolution "
277 "screen\n"));
278
279#ifdef EXP_ZOOM_LEVELS
280 fc_fprintf(stderr,
281 /* TRANS: Keep word 'default' untranslated */
282 _("-z, --zoom LEVEL\tSet zoom level; use value 'default' "
283 "to reset\n\n"));
284#else
285 fc_fprintf(stderr, "\n");
286#endif /* EXP_ZOOM_LEVELS */
287
288 /* TRANS: No full stop after the URL, could cause confusion. */
289 fc_fprintf(stderr, _("Report bugs at %s\n"), BUG_URL);
290}
291
292/**********************************************************************/
295 static bool parse_options(int argc, char **argv)
296{
297 int i = 1;
298
299 while (i < argc) {
300 char *option = NULL;
301
302 if (is_option("--help", argv[i])) {
303 print_usage();
304
305 return FALSE;
306
307#ifdef EXP_ZOOM_LEVELS
308 } else if ((option = get_option_malloc("--zoom", argv, &i, argc, FALSE))) {
309 char *endptr;
310
311 if (strcmp("default", option)) {
312 gui_options.zoom_set = TRUE;
313 gui_options.zoom_default_level = strtof(option, &endptr);
314 } else {
315 gui_options.zoom_set = FALSE;
316 }
317 free(option);
318#endif /* EXP_ZOOM_LEVELS */
319
320 } else if ((option = get_option_malloc("--resolution", argv, &i, argc, FALSE))) {
321 if (!string_to_video_mode(option, &vmode)) {
322 fc_fprintf(stderr, _("Illegal video mode '%s'\n"), option);
323 exit(EXIT_FAILURE);
324 }
325 free(option);
326 } else {
327 fc_fprintf(stderr, _("Unknown command-line option \"%s\".\n"),
328 argv[i]);
329 exit(EXIT_FAILURE);
330 }
331
332 i++;
333 }
334
335 return TRUE;
336}
337
338/**********************************************************************/
341 static void toplevel_focus(GtkWidget *w, GtkDirectionType arg,
342 gpointer data)
343{
344 switch (arg) {
345 case GTK_DIR_TAB_FORWARD:
346 case GTK_DIR_TAB_BACKWARD:
347
348 if (!gtk_widget_get_can_focus(w)) {
349 return;
350 }
351
352 if (!gtk_widget_is_focus(w)) {
353 gtk_widget_grab_focus(w);
354 return;
355 }
356 break;
357
358 default:
359 break;
360 }
361}
362
363/**********************************************************************/
368 void main_message_area_resize(void *data)
369{
370 if (get_current_client_page() == PAGE_GAME) {
371 static int old_width = 0, old_height = 0;
372 int width = gtk_widget_get_width(GTK_WIDGET(main_message_area));
373 int height = gtk_widget_get_height(GTK_WIDGET(main_message_area));
374
375 if (width != old_width
376 || height != old_height) {
377 chatline_scroll_to_bottom(TRUE);
378 old_width = width;
379 old_height = height;
380 }
381
382 add_idle_callback(main_message_area_resize, NULL);
383 }
384}
385
386/**********************************************************************/
389 gboolean map_canvas_focus(void)
390{
391 gtk_window_present(GTK_WINDOW(toplevel));
392 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 0);
393 gtk_widget_grab_focus(map_canvas);
394
395 return TRUE;
396}
397
398/**********************************************************************/
401 static gboolean key_press_map_canvas(guint keyval, GdkModifierType state)
402{
403 if ((state & GDK_SHIFT_MASK)) {
404 switch (keyval) {
405
406 case GDK_KEY_Left:
407 scroll_mapview(DIR8_WEST);
408 return TRUE;
409
410 case GDK_KEY_Right:
411 scroll_mapview(DIR8_EAST);
412 return TRUE;
413
414 case GDK_KEY_Up:
415 scroll_mapview(DIR8_NORTH);
416 return TRUE;
417
418 case GDK_KEY_Down:
419 scroll_mapview(DIR8_SOUTH);
420 return TRUE;
421
422 case GDK_KEY_Home:
423 key_center_capital();
424 return TRUE;
425
426 case GDK_KEY_Page_Up:
427 g_signal_emit_by_name(main_message_area, "move_cursor",
428 GTK_MOVEMENT_PAGES, -1, FALSE);
429 return TRUE;
430
431 case GDK_KEY_Page_Down:
432 g_signal_emit_by_name(main_message_area, "move_cursor",
433 GTK_MOVEMENT_PAGES, 1, FALSE);
434 return TRUE;
435
436 default:
437 break;
438 }
439 } else if (!(state & GDK_CONTROL_MASK)) {
440 switch (keyval) {
441 default:
442 break;
443 }
444 }
445
446 if (state & GDK_SHIFT_MASK) {
447 bool volchange = FALSE;
448
449 switch (keyval) {
450 case GDK_KEY_plus:
451 case GDK_KEY_KP_Add:
452 gui_options.sound_effects_volume += 10;
453 volchange = TRUE;
454 break;
455
456 case GDK_KEY_minus:
457 case GDK_KEY_KP_Subtract:
458 gui_options.sound_effects_volume -= 10;
459 volchange = TRUE;
460 break;
461
462 default:
463 break;
464 }
465
466 if (volchange) {
467 struct option *poption = optset_option_by_name(client_optset,
468 "sound_effects_volume");
469
470 gui_options.sound_effects_volume = CLIP(0,
471 gui_options.sound_effects_volume,
472 100);
473 option_changed(poption);
474
475 return TRUE;
476 }
477 } else if (!(state & GDK_CONTROL_MASK)) {
478 switch (keyval) {
479 case GDK_KEY_plus:
480 case GDK_KEY_KP_Add:
481 zoom_step_up();
482 return TRUE;
483
484 case GDK_KEY_minus:
485 case GDK_KEY_KP_Subtract:
486 zoom_step_down();
487 return TRUE;
488
489 default:
490 break;
491 }
492 }
493
494 /* Return here if observer */
495 if (client_is_observer()) {
496 return FALSE;
497 }
498
499 switch (keyval) {
500
501 case GDK_KEY_KP_Up:
502 case GDK_KEY_KP_8:
503 case GDK_KEY_Up:
504 case GDK_KEY_8:
505 key_unit_move(DIR8_NORTH);
506 return TRUE;
507
508 case GDK_KEY_KP_Page_Up:
509 case GDK_KEY_KP_9:
510 case GDK_KEY_Page_Up:
511 case GDK_KEY_9:
512 key_unit_move(DIR8_NORTHEAST);
513 return TRUE;
514
515 case GDK_KEY_KP_Right:
516 case GDK_KEY_KP_6:
517 case GDK_KEY_Right:
518 case GDK_KEY_6:
519 key_unit_move(DIR8_EAST);
520 return TRUE;
521
522 case GDK_KEY_KP_Page_Down:
523 case GDK_KEY_KP_3:
524 case GDK_KEY_Page_Down:
525 case GDK_KEY_3:
526 key_unit_move(DIR8_SOUTHEAST);
527 return TRUE;
528
529 case GDK_KEY_KP_Down:
530 case GDK_KEY_KP_2:
531 case GDK_KEY_Down:
532 case GDK_KEY_2:
533 key_unit_move(DIR8_SOUTH);
534 return TRUE;
535
536 case GDK_KEY_KP_End:
537 case GDK_KEY_KP_1:
538 case GDK_KEY_End:
539 case GDK_KEY_1:
540 key_unit_move(DIR8_SOUTHWEST);
541 return TRUE;
542
543 case GDK_KEY_KP_Left:
544 case GDK_KEY_KP_4:
545 case GDK_KEY_Left:
546 case GDK_KEY_4:
547 key_unit_move(DIR8_WEST);
548 return TRUE;
549
550 case GDK_KEY_KP_Home:
551 case GDK_KEY_KP_7:
552 case GDK_KEY_Home:
553 case GDK_KEY_7:
554 key_unit_move(DIR8_NORTHWEST);
555 return TRUE;
556
557 case GDK_KEY_KP_Begin:
558 case GDK_KEY_KP_5:
559 case GDK_KEY_5:
560 key_recall_previous_focus_unit();
561 return TRUE;
562
563 case GDK_KEY_Escape:
564 key_cancel_action();
565 return TRUE;
566
567 case GDK_KEY_b:
568 if (tiles_hilited_cities) {
569 buy_production_in_selected_cities();
570 return TRUE;
571 }
572 break;
573
574 default:
575 break;
576 };
577
578 return FALSE;
579}
580
581/**********************************************************************/
584 static gboolean toplevel_key_press_handler(GtkEventControllerKey *controller,
585 guint keyval,
586 guint keycode,
587 GdkModifierType state,
588 gpointer data)
589{
590 if (inputline_has_focus()) {
591 return FALSE;
592 }
593
594 if (keyval == GDK_KEY_apostrophe) {
595 /* Allow this even if not in main map view; chatline is present on
596 * some other pages too */
597
598 /* Make the chatline visible if it's not currently.
599 * FIXME: should find the correct window, even when detached, from any
600 * other window; should scroll to the bottom automatically showing the
601 * latest text from other players; MUST NOT make spurious text windows
602 * at the bottom of other dialogs. */
603 if (gtk_widget_get_mapped(top_vbox)) {
604 /* The main game view is visible. May need to switch notebook. */
605 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
606 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 1);
607 } else {
608 gtk_notebook_set_current_page(GTK_NOTEBOOK(bottom_notebook), 0);
609 }
610 }
611
612 /* If the chatline is (now) visible, focus it. */
613 if (inputline_is_visible()) {
614 inputline_grab_focus();
615 return TRUE;
616 }
617 }
618
619 if (!gtk_widget_get_mapped(top_vbox)
620 || !can_client_change_view()) {
621 return FALSE;
622 }
623
624 if (editor_is_active()) {
625 if (handle_edit_key_press(keyval, state)) {
626 return TRUE;
627 }
628 }
629
630 if (state & GDK_SHIFT_MASK) {
631 switch (keyval) {
632
633 case GDK_KEY_Return:
634 case GDK_KEY_KP_Enter:
635 key_end_turn();
636 return TRUE;
637
638 default:
639 break;
640 }
641 }
642
643 if (0 == gtk_notebook_get_current_page(GTK_NOTEBOOK(top_notebook))) {
644 /* 0 means the map view is focused. */
645 return key_press_map_canvas(keyval, state);
646 }
647
648#if 0
649 /* We are focused some other dialog, tab, or widget. */
650 if ((state & GDK_CONTROL_MASK)) {
651 } else if ((state & GDK_SHIFT_MASK)) {
652 } else {
653 switch (keyval) {
654
655 case GDK_KEY_F4:
656 map_canvas_focus();
657 return TRUE;
658
659 default:
660 break;
661 };
662 }
663#endif /* 0 */
664
665 return FALSE;
666}
667
668/**********************************************************************/
671 static gboolean mouse_scroll_mapcanvas(GtkEventControllerScroll *controller,
672 gdouble dx, gdouble dy,
673 gpointer data)
674{
675 int scroll_x, scroll_y, xstep, ystep;
676 gdouble e_x, e_y;
677 GdkModifierType state;
678
679 if (!can_client_change_view()) {
680 return FALSE;
681 }
682
683 get_mapview_scroll_pos(&scroll_x, &scroll_y);
684 get_mapview_scroll_step(&xstep, &ystep);
685
686 scroll_y += ystep * dy;
687 scroll_x += xstep * dx;
688
689 set_mapview_scroll_pos(scroll_x, scroll_y, mouse_zoom);
690
691 /* Emulating mouse move now */
692 if (!gtk_widget_has_focus(map_canvas)) {
693 gtk_widget_grab_focus(map_canvas);
694 }
695
696 gdk_event_get_position(gtk_event_controller_get_current_event(
697 GTK_EVENT_CONTROLLER(controller)),
698 &e_x, &e_y);
699 update_line(e_x, e_y);
700 state = gtk_event_controller_get_current_event_state(
701 GTK_EVENT_CONTROLLER(controller));
702 if (rbutton_down && (state & GDK_BUTTON3_MASK)) {
703 update_selection_rectangle(e_x, e_y);
704 }
705
706 if (keyboardless_goto_button_down && hover_state == HOVER_NONE) {
707 maybe_activate_keyboardless_goto(cur_x, cur_y);
708 }
709
710 control_mouse_cursor(canvas_pos_to_tile(cur_x, cur_y, mouse_zoom));
711
712 return TRUE;
713}
714
715/**********************************************************************/
718 static void move_from_container_to_container(GtkWidget *wdg,
719 GtkWidget *old_wdg,
720 GtkWidget *new_wdg)
721{
722 g_object_ref(wdg); /* Make sure reference count stays above 0
723 * during the transition to new parent. */
724
725 if (GTK_IS_PANED(old_wdg)) {
726 gtk_paned_set_end_child(GTK_PANED(old_wdg), NULL);
727 } else if (GTK_IS_WINDOW(old_wdg)) {
728 gtk_window_set_child(GTK_WINDOW(old_wdg), NULL);
729 } else {
730 fc_assert(GTK_IS_BOX(old_wdg));
731
732 gtk_box_remove(GTK_BOX(old_wdg), wdg);
733 }
734
735 if (GTK_IS_PANED(new_wdg)) {
736 gtk_paned_set_end_child(GTK_PANED(new_wdg), wdg);
737 } else if (GTK_IS_WINDOW(new_wdg)) {
738 gtk_window_set_child(GTK_WINDOW(new_wdg), wdg);
739 } else {
740 fc_assert(GTK_IS_BOX(new_wdg));
741
742 gtk_box_append(GTK_BOX(new_wdg), wdg);
743 }
744
745 g_object_unref(wdg);
746}
747
748/**********************************************************************/
751 gboolean fc_lost_focus(GtkEventControllerFocus *controller,
752 gpointer data)
753{
754 client_focus = FALSE;
755
756 return TRUE;
757}
758
759/**********************************************************************/
762 gboolean fc_gained_focus(GtkEventControllerFocus *controller,
763 gpointer data)
764{
765 client_focus = TRUE;
766
767 return TRUE;
768}
769
770/**********************************************************************/
773 static void tearoff_reattach(GtkWidget *box)
774{
775 GtkWidget *aparent, *cparent;
776
777 aparent = g_object_get_data(G_OBJECT(box), "aparent");
778 cparent = gtk_widget_get_parent(box);
779
780 if (aparent != cparent) {
781 move_from_container_to_container(box, cparent, aparent);
782
783 gtk_window_destroy(GTK_WINDOW(cparent));
784 }
785}
786
787/**********************************************************************/
790 static void tearoff_close(GtkWidget *w, gpointer data)
791{
792 tearoff_reattach(GTK_WIDGET(data));
793}
794
795/**********************************************************************/
799 static void tearoff_callback(GtkWidget *b, gpointer data)
800{
801 GtkWidget *box = GTK_WIDGET(data);
802 GtkWidget *old_parent = gtk_widget_get_parent(box);
803
804 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b))) {
805 GtkWidget *w;
806 GtkWidget *temp_hide;
807
808 w = gtk_window_new();
809 setup_dialog(w, toplevel);
810 gtk_widget_set_name(w, "Freeciv");
811 gtk_window_set_title(GTK_WINDOW(w), _("Freeciv"));
812 g_signal_connect(w, "close-request", G_CALLBACK(tearoff_close), box);
813
814 g_object_set_data(G_OBJECT(box), "aparent", gtk_widget_get_parent(box));
815
816 temp_hide = g_object_get_data(G_OBJECT(box), "hide-over-reparent");
817 if (temp_hide != nullptr) {
818 gtk_widget_set_visible(temp_hide, FALSE);
819 }
820
821 move_from_container_to_container(box, old_parent, w);
822
823 gtk_widget_set_visible(w, TRUE);
824
825 if (temp_hide != nullptr) {
826 gtk_widget_set_visible(temp_hide, TRUE);
827 }
828 } else {
829 tearoff_reattach(box);
830 }
831}
832
833/**********************************************************************/
836 static GtkWidget *detached_widget_new(void)
837{
838 GtkWidget *hbox = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 2);
839
840 return hbox;
841}
842
843/**********************************************************************/
847 static GtkWidget *detached_widget_fill(GtkWidget *tearbox)
848{
849 GtkWidget *b, *fillbox;
850 static GtkCssProvider *detach_button_provider = NULL;
851
852 if (detach_button_provider == NULL) {
853 detach_button_provider = gtk_css_provider_new();
854
855 /* These toggle buttons run vertically down the side of many UI
856 * elements, so they need to be thin horizontally. */
857 gtk_css_provider_load_from_data(detach_button_provider,
858 ".detach_button {\n"
859 " padding: 0px 0px 0px 0px;\n"
860 " min-width: 6px;\n"
861 "}",
862 -1);
863 }
864
865 b = gtk_toggle_button_new();
866 gtk_style_context_add_provider_for_display(
867 gtk_widget_get_display(toplevel),
868 GTK_STYLE_PROVIDER(detach_button_provider),
869 GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
870 gtk_widget_add_css_class(b, "detach_button");
871
872 gtk_box_append(GTK_BOX(tearbox), b);
873 g_signal_connect(b, "toggled", G_CALLBACK(tearoff_callback), tearbox);
874
875 fillbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
876
877 gtk_box_append(GTK_BOX(tearbox), fillbox);
878
879 return fillbox;
880}
881
882/**********************************************************************/
889 static void populate_unit_pic_table(void)
890{
891 int i, width;
892 GtkWidget *table = unit_pic_table;
893 GdkPixbuf *pix;
894 int ttw;
895 GtkEventController *controller;
896
897 /* Get width of the overview window */
898 width = (overview_canvas_store_width > GUI_GTK_OVERVIEW_MIN_XSIZE)
899 ? overview_canvas_store_width
900 : GUI_GTK_OVERVIEW_MIN_XSIZE;
901
902 ttw = tileset_tile_width(tileset);
903
904 if (GUI_GTK_OPTION(small_display_layout)) {
905 /* We want arrow to appear if there is other units in addition
906 to active one in tile. Active unit is not counted, so there
907 can be 0 other units to not to display arrow. */
908 num_units_below = 1 - 1;
909 } else {
910 num_units_below = width / ttw;
911 num_units_below = CLIP(1, num_units_below, MAX_NUM_UNITS_BELOW);
912 }
913
914 /* Top row: the active unit. */
915 /* Note, we ref this and other widgets here so that we can unref them
916 * in reset_unit_table. */
917 unit_pic = gtk_picture_new();
918 g_object_ref(unit_pic);
919 gtk_widget_set_size_request(unit_pic, ttw, -1);
920 gtk_grid_attach(GTK_GRID(table), unit_pic, 0, 0, 1, 1);
921
922 controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
923 g_signal_connect(controller, "pressed",
924 G_CALLBACK(select_unit_pic_callback),
925 GINT_TO_POINTER(-1));
926 gtk_widget_add_controller(unit_pic, controller);
927
928 if (!GUI_GTK_OPTION(small_display_layout)) {
929 /* Bottom row: other units in the same tile. */
930 for (i = 0; i < num_units_below; i++) {
931 unit_below_pic[i] = gtk_picture_new();
932 g_object_ref(unit_below_pic[i]);
933 gtk_widget_set_size_request(unit_below_pic[i], ttw, -1);
934
935 controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
936 g_signal_connect(controller, "pressed",
937 G_CALLBACK(select_unit_pic_callback),
938 GINT_TO_POINTER(i));
939 gtk_widget_add_controller(unit_below_pic[i], controller);
940
941 gtk_grid_attach(GTK_GRID(table), unit_below_pic[i],
942 i, 1, 1, 1);
943 }
944 }
945
946 /* Create arrow (popup for all units on the selected tile) */
947 pix = sprite_get_pixbuf(get_arrow_sprite(tileset, ARROW_RIGHT));
948 more_arrow = gtk_image_new_from_pixbuf(pix);
949 g_object_ref(more_arrow);
950
951 controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
952 g_signal_connect(controller, "pressed",
953 G_CALLBACK(select_more_arrow_callback),
954 NULL);
955 gtk_widget_add_controller(more_arrow, controller);
956
957 /* An extra layer so that we can hide the clickable button but keep
958 * an explicit size request to avoid the layout jumping around */
959 more_arrow_container = gtk_frame_new(NULL);
960 gtk_widget_set_halign(more_arrow_container, GTK_ALIGN_CENTER);
961 gtk_widget_set_valign(more_arrow_container, GTK_ALIGN_CENTER);
962 g_object_ref(more_arrow_container);
963 gtk_frame_set_child(GTK_FRAME(more_arrow_container), more_arrow);
964 gtk_widget_set_size_request(more_arrow_container,
965 gdk_pixbuf_get_width(pix), -1);
966 g_object_unref(G_OBJECT(pix));
967
968 if (!GUI_GTK_OPTION(small_display_layout)) {
969 /* Display on bottom row. */
970 gtk_grid_attach(GTK_GRID(table), more_arrow_container,
971 num_units_below, 1, 1, 1);
972 } else {
973 /* Display on top row (there is no bottom row). */
974 gtk_grid_attach(GTK_GRID(table), more_arrow_container,
975 1, 0, 1, 1);
976 }
977
978 gtk_widget_set_visible(table, TRUE);
979}
980
981/**********************************************************************/
984 static void free_unit_table(void)
985{
986 if (unit_pic != NULL) {
987 gtk_grid_remove(GTK_GRID(unit_pic_table), unit_pic);
988 g_object_unref(unit_pic);
989 if (!GUI_GTK_OPTION(small_display_layout)) {
990 int i;
991
992 for (i = 0; i < num_units_below; i++) {
993 gtk_grid_remove(GTK_GRID(unit_pic_table),
994 unit_below_pic[i]);
995 g_object_unref(unit_below_pic[i]);
996 }
997 }
998 gtk_grid_remove(GTK_GRID(unit_pic_table),
999 more_arrow_container);
1000 g_object_unref(more_arrow);
1001 g_object_unref(more_arrow_container);
1002 }
1003}
1004
1005/**********************************************************************/
1008 void reset_unit_table(void)
1009{
1010 /* Unreference all of the widgets that we're about to reallocate, thus
1011 * avoiding a memory leak. Remove them from the container first, just
1012 * to be safe. Note, the widgets are ref'd in
1013 * populate_unit_pic_table(). */
1014 free_unit_table();
1015
1016 populate_unit_pic_table();
1017
1018 /* We have to force a redraw of the units. And we explicitly have
1019 * to force a redraw of the focus unit, which is normally only
1020 * redrawn when the focus changes. We also have to force the 'more'
1021 * arrow to go away, both by expicitly hiding it and telling it to
1022 * do so (this will be reset immediately afterwards if necessary,
1023 * but we have to make the *internal* state consistent). */
1024 gtk_widget_set_visible(more_arrow, FALSE);
1025 set_unit_icons_more_arrow(FALSE);
1026 if (get_num_units_in_focus() == 1) {
1027 set_unit_icon(-1, head_of_units_in_focus());
1028 } else {
1029 set_unit_icon(-1, NULL);
1030 }
1031 update_unit_pix_label(get_units_in_focus());
1032}
1033
1034/**********************************************************************/
1037#if 0
1038static void setup_canvas_color_for_state(GtkStateFlags state)
1039{
1040 gtk_widget_override_background_color(GTK_WIDGET(overview_canvas), state,
1041 &get_color(tileset, COLOR_OVERVIEW_UNKNOWN)->color);
1042 gtk_widget_override_background_color(GTK_WIDGET(map_canvas), state,
1043 &get_color(tileset, COLOR_OVERVIEW_UNKNOWN)->color);
1044}
1045#endif
1046
1047/**********************************************************************/
1050 gboolean terminate_signal_processing(GtkEventControllerFocus *controller,
1051 gpointer data)
1052{
1053 return TRUE;
1054}
1055
1056/**********************************************************************/
1059 void update_turn_done_tooltip(void)
1060{
1061 struct option *opt = optset_option_by_name(server_optset, "fixedlength");
1062
1063 if (opt != NULL && option_bool_get(opt)) {
1064 gtk_widget_set_tooltip_text(turn_done_button,
1065 _("Fixed length turns"));
1066 } else {
1067 char buf[256];
1068
1069 fc_snprintf(buf, sizeof(buf), "%s:\n%s",
1070 _("Turn Done"), _("Shift+Return"));
1071 gtk_widget_set_tooltip_text(turn_done_button, buf);
1072 }
1073}
1074
1075/**********************************************************************/
1078 static void setup_widgets(void)
1079{
1080 GtkWidget *page, *hgrid, *hgrid2, *label;
1081 GtkWidget *frame, *table, *table2, *paned, *sw, *text;
1082 GtkWidget *button, *view, *mainbox, *vbox, *right_vbox = NULL;
1083 int i;
1084 GtkWidget *notebook, *statusbar;
1085 GtkWidget *dtach_lowbox = NULL;
1086 struct sprite *spr;
1087 int right_row = 0;
1088 int top_row = 0;
1089 int grid_col = 0;
1090 int grid2_col = 0;
1091 GtkGesture *mc_gesture;
1092 GtkEventController *mc_controller;
1093 GtkWidget *ebar;
1094
1095 message_buffer = gtk_text_buffer_new(NULL);
1096
1097 notebook = gtk_notebook_new();
1098
1099 toplevel_tabs = notebook;
1100 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1101 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1102 mainbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 4);
1103 gtk_window_set_child(GTK_WINDOW(toplevel), mainbox);
1104 gtk_box_append(GTK_BOX(mainbox), notebook);
1105 statusbar = create_statusbar();
1106 gtk_box_append(GTK_BOX(mainbox), statusbar);
1107
1108 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1109 create_main_page(), NULL);
1110 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1111 create_start_page(), NULL);
1112 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1113 create_scenario_page(), NULL);
1114 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1115 create_load_page(), NULL);
1116 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1117 create_network_page(), NULL);
1118
1119 editgui_create_widgets();
1120
1121 ingame_votebar = voteinfo_bar_new(FALSE);
1122 gtk_widget_set_margin_bottom(ingame_votebar, 2);
1123 gtk_widget_set_margin_end(ingame_votebar, 2);
1124 gtk_widget_set_margin_start(ingame_votebar, 2);
1125 gtk_widget_set_margin_top(ingame_votebar, 2);
1126
1127 /* *** Everything in the top *** */
1128
1129 page = gtk_scrolled_window_new();
1130 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page),
1131 GTK_POLICY_AUTOMATIC,
1132 GTK_POLICY_AUTOMATIC);
1133 gtk_scrolled_window_set_has_frame(GTK_SCROLLED_WINDOW(page),
1134 TRUE);
1135 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, NULL);
1136
1137 top_vbox = gtk_grid_new();
1138 gtk_orientable_set_orientation(GTK_ORIENTABLE(top_vbox),
1139 GTK_ORIENTATION_VERTICAL);
1140 gtk_grid_set_row_spacing(GTK_GRID(top_vbox), 5);
1141 hgrid = gtk_grid_new();
1142
1143 if (GUI_GTK_OPTION(small_display_layout)) {
1144 /* The window is divided into two horizontal panels: overview +
1145 * civinfo + unitinfo, main view + message window. */
1146 right_vbox = gtk_grid_new();
1147 right_row = 0;
1148 gtk_orientable_set_orientation(GTK_ORIENTABLE(right_vbox),
1149 GTK_ORIENTATION_VERTICAL);
1150 gtk_grid_attach(GTK_GRID(hgrid), right_vbox, grid_col++, 0, 1, 1);
1151
1152 paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
1153 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(page), top_vbox);
1154 gtk_grid_attach(GTK_GRID(top_vbox), hgrid, 0, top_row++, 1, 1);
1155 gtk_grid_attach(GTK_GRID(right_vbox), paned, 0, right_row++, 1, 1);
1156 gtk_grid_attach(GTK_GRID(right_vbox), ingame_votebar, 0, right_row++, 1, 1);
1157
1158 /* Overview size designed for small displays (netbooks). */
1159 overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK;
1160 overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK;
1161 } else {
1162 /* The window is divided into two vertical panes: overview +
1163 * + civinfo + unitinfo + main view, message window. */
1164 paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1165 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(page), paned);
1166 gtk_paned_set_start_child(GTK_PANED(paned), top_vbox);
1167 gtk_grid_attach(GTK_GRID(top_vbox), hgrid, 0, top_row++, 1, 1);
1168
1169 /* Overview size designed for big displays (desktops). */
1170 overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH;
1171 overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT;
1172 }
1173
1174 /* This holds the overview canvas, production info, etc. */
1175 vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 3);
1176 /* Put vbox to the left of anything else in hgrid -- right_vbox is either
1177 * the chat/messages pane, or NULL which is OK */
1178 gtk_grid_attach_next_to(GTK_GRID(hgrid), vbox, right_vbox,
1179 GTK_POS_LEFT, 1, 1);
1180 grid_col++;
1181
1182 /* Overview canvas */
1183 ahbox = detached_widget_new();
1184 gtk_widget_set_hexpand(ahbox, FALSE);
1185 gtk_widget_set_vexpand(ahbox, FALSE);
1186 gtk_box_append(GTK_BOX(vbox), ahbox);
1187 avbox = detached_widget_fill(ahbox);
1188
1189 overview_scrolled_window = gtk_scrolled_window_new();
1190 gtk_widget_set_margin_start(overview_scrolled_window, 1);
1191 gtk_widget_set_margin_end(overview_scrolled_window, 1);
1192 gtk_widget_set_margin_top(overview_scrolled_window, 1);
1193 gtk_widget_set_margin_bottom(overview_scrolled_window, 1);
1194 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (overview_scrolled_window),
1195 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1196
1197 overview_canvas = gtk_drawing_area_new();
1198 gtk_widget_set_halign(overview_canvas, GTK_ALIGN_CENTER);
1199 gtk_widget_set_valign(overview_canvas, GTK_ALIGN_CENTER);
1200 gtk_widget_set_size_request(overview_canvas, overview_canvas_store_width,
1201 overview_canvas_store_height);
1202 gtk_widget_set_size_request(overview_scrolled_window, overview_canvas_store_width,
1203 overview_canvas_store_height);
1204 gtk_widget_set_hexpand(overview_canvas, TRUE);
1205 gtk_widget_set_vexpand(overview_canvas, TRUE);
1206
1207 gtk_box_append(GTK_BOX(avbox), overview_scrolled_window);
1208
1209 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(overview_scrolled_window),
1210 overview_canvas);
1211
1212 gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(overview_canvas),
1213 overview_canvas_draw, NULL, NULL);
1214
1215 mc_controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
1216 g_signal_connect(mc_controller, "pressed",
1217 G_CALLBACK(left_butt_down_overviewcanvas), NULL);
1218 gtk_widget_add_controller(overview_canvas, mc_controller);
1219 mc_gesture = gtk_gesture_click_new();
1220 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(mc_gesture), 3);
1221 mc_controller = GTK_EVENT_CONTROLLER(mc_gesture);
1222 g_signal_connect(mc_controller, "pressed",
1223 G_CALLBACK(right_butt_down_overviewcanvas), NULL);
1224 gtk_widget_add_controller(overview_canvas, mc_controller);
1225 mc_controller = gtk_event_controller_motion_new();
1226 g_signal_connect(mc_controller, "motion",
1227 G_CALLBACK(move_overviewcanvas), NULL);
1228 gtk_widget_add_controller(overview_canvas, mc_controller);
1229
1230 /* The rest */
1231 ahbox = detached_widget_new();
1232 gtk_box_append(GTK_BOX(vbox), ahbox);
1233 gtk_widget_set_hexpand(ahbox, FALSE);
1234 avbox = detached_widget_fill(ahbox);
1235 gtk_widget_set_vexpand(avbox, TRUE);
1236 gtk_widget_set_valign(avbox, GTK_ALIGN_FILL);
1237
1238 /* Info on player's civilization, when game is running. */
1239 frame = gtk_frame_new("");
1240 gtk_box_append(GTK_BOX(avbox), frame);
1241
1242 main_frame_civ_name = frame;
1243
1244 mainbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
1245 gtk_frame_set_child(GTK_FRAME(frame), mainbox);
1246 gtk_widget_set_hexpand(mainbox, TRUE);
1247
1248 label = gtk_label_new(NULL);
1249 gtk_widget_set_halign(label, GTK_ALIGN_START);
1250 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
1251 gtk_widget_set_margin_start(label, 2);
1252 gtk_widget_set_margin_end(label, 2);
1253 gtk_widget_set_margin_top(label, 2);
1254 gtk_widget_set_margin_bottom(label, 2);
1255
1256 mc_controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
1257 g_signal_connect(mc_controller, "pressed",
1258 G_CALLBACK(show_info_popup), frame);
1259 gtk_widget_add_controller(label, mc_controller);
1260 gtk_box_append(GTK_BOX(mainbox), label);
1261 main_label_info = label;
1262
1263 /* Production status */
1264 table = gtk_grid_new();
1265 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
1266 gtk_grid_set_column_homogeneous(GTK_GRID(table), TRUE);
1267 gtk_box_append(GTK_BOX(avbox), table);
1268
1269 /* Citizens for taxrates */
1270 table2 = gtk_grid_new();
1271 gtk_grid_attach(GTK_GRID(table), table2, 0, 0, 10, 1);
1272 econ_widget = table2;
1273
1274 for (i = 0; i < 10; i++) {
1275 GtkEventController *controller;
1276
1277 spr = i < 5 ? get_tax_sprite(tileset, O_SCIENCE) : get_tax_sprite(tileset, O_GOLD);
1278 econ_label[i] = picture_new_from_surface(spr->surface);
1279
1280 g_object_set_data(G_OBJECT(econ_label[i]), "rate_button", GUINT_TO_POINTER(i));
1281 controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
1282 g_signal_connect(controller, "pressed",
1283 G_CALLBACK(taxrates_callback), NULL);
1284 gtk_widget_add_controller(econ_label[i], controller);
1285 mc_gesture = gtk_gesture_click_new();
1286 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(mc_gesture), 3);
1287 controller = GTK_EVENT_CONTROLLER(mc_gesture);
1288 g_signal_connect(controller, "pressed",
1289 G_CALLBACK(reverse_taxrates_callback), NULL);
1290 gtk_widget_add_controller(econ_label[i], controller);
1291 gtk_grid_attach(GTK_GRID(table2), econ_label[i], i, 0, 1, 1);
1292 }
1293
1294 /* Science, environmental, govt, timeout */
1295 spr = client_research_sprite();
1296 if (spr != NULL) {
1297 bulb_label = picture_new_from_surface(spr->surface);
1298 } else {
1299 bulb_label = gtk_picture_new();
1300 }
1301
1302 spr = client_warming_sprite();
1303 if (spr != NULL) {
1304 sun_label = picture_new_from_surface(spr->surface);
1305 } else {
1306 sun_label = gtk_picture_new();
1307 }
1308
1309 spr = client_cooling_sprite();
1310 if (spr != NULL) {
1311 flake_label = picture_new_from_surface(spr->surface);
1312 } else {
1313 flake_label = gtk_picture_new();
1314 }
1315
1316 spr = client_government_sprite();
1317 if (spr != NULL) {
1318 government_label = picture_new_from_surface(spr->surface);
1319 } else {
1320 government_label = gtk_picture_new();
1321 }
1322
1323 for (i = 0; i < 4; i++) {
1324 GtkWidget *w;
1325
1326 switch (i) {
1327 case 0:
1328 w = bulb_label;
1329 break;
1330 case 1:
1331 w = sun_label;
1332 break;
1333 case 2:
1334 w = flake_label;
1335 break;
1336 default:
1337 case 3:
1338 w = government_label;
1339 break;
1340 }
1341
1342 gtk_widget_set_halign(w, GTK_ALIGN_START);
1343 gtk_widget_set_valign(w, GTK_ALIGN_START);
1344 gtk_widget_set_margin_start(w, 0);
1345 gtk_widget_set_margin_end(w, 0);
1346 gtk_widget_set_margin_top(w, 0);
1347 gtk_widget_set_margin_bottom(w, 0);
1348 gtk_grid_attach(GTK_GRID(table), w, i, 1, 1, 1);
1349 }
1350
1351 timeout_label = gtk_label_new("");
1352
1353 frame = gtk_frame_new(NULL);
1354 gtk_grid_attach(GTK_GRID(table), frame, 4, 1, 6, 1);
1355 gtk_frame_set_child(GTK_FRAME(frame), timeout_label);
1356
1357
1358 /* Turn done */
1359 turn_done_button = gtk_button_new_with_label(_("Turn Done"));
1360
1361 gtk_grid_attach(GTK_GRID(table), turn_done_button, 0, 2, 10, 1);
1362
1363 g_signal_connect(turn_done_button, "clicked",
1364 G_CALLBACK(end_turn_callback), NULL);
1365 update_turn_done_tooltip();
1366
1367 /* Selected unit status */
1368
1369 /* If you turn this to something else than GtkBox, also adjust
1370 * editgui.c replace_widget() code that removes and adds widgets from it. */
1371 unit_info_box = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
1372 gtk_widget_set_hexpand(unit_info_box, FALSE);
1373 gtk_box_append(GTK_BOX(avbox), unit_info_box);
1374
1375 /* In edit mode the unit_info_box widget is replaced by the
1376 * editinfobox, so we need to add a ref here so that it is
1377 * not destroyed when removed from its container.
1378 * See editinfobox_refresh() call to replace_widget() */
1379 g_object_ref(unit_info_box);
1380
1381 unit_info_frame = gtk_frame_new("");
1382 gtk_box_append(GTK_BOX(unit_info_box), unit_info_frame);
1383
1384 sw = gtk_scrolled_window_new();
1385 gtk_scrolled_window_set_has_frame(GTK_SCROLLED_WINDOW(sw), TRUE);
1386 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1387 GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
1388 gtk_frame_set_child(GTK_FRAME(unit_info_frame), sw);
1389
1390 label = gtk_label_new(NULL);
1391 gtk_widget_set_hexpand(label, TRUE);
1392 gtk_widget_set_halign(label, GTK_ALIGN_START);
1393 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
1394 gtk_widget_set_margin_start(label, 2);
1395 gtk_widget_set_margin_end(label, 2);
1396 gtk_widget_set_margin_top(label, 2);
1397 gtk_widget_set_margin_bottom(label, 2);
1398 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), label);
1399 unit_info_label = label;
1400
1401 hgrid2 = gtk_grid_new();
1402 gtk_box_append(GTK_BOX(unit_info_box), hgrid2);
1403
1404 table = gtk_grid_new();
1405 gtk_widget_set_margin_bottom(table, 5);
1406 gtk_widget_set_margin_end(table, 5);
1407 gtk_widget_set_margin_start(table, 5);
1408 gtk_widget_set_margin_top(table, 5);
1409 gtk_grid_attach(GTK_GRID(hgrid2), table, grid2_col++, 0, 1, 1);
1410
1411 gtk_grid_set_row_spacing(GTK_GRID(table), 2);
1412 gtk_grid_set_column_spacing(GTK_GRID(table), 2);
1413
1414 unit_pic_table = table;
1415
1416 /* Map canvas, editor toolbar, and scrollbars */
1417
1418 /* The top notebook containing the map view and dialogs. */
1419
1420 top_notebook = gtk_notebook_new();
1421 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(top_notebook), GTK_POS_BOTTOM);
1422 gtk_notebook_set_scrollable(GTK_NOTEBOOK(top_notebook), TRUE);
1423
1424
1425 if (GUI_GTK_OPTION(small_display_layout)) {
1426 gtk_paned_set_start_child(GTK_PANED(paned), top_notebook);
1427 } else if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
1428 right_vbox = gtk_grid_new();
1429 right_row = 0;
1430 gtk_orientable_set_orientation(GTK_ORIENTABLE(right_vbox),
1431 GTK_ORIENTATION_VERTICAL);
1432
1433 gtk_grid_attach(GTK_GRID(right_vbox), top_notebook, 0, right_row++, 1, 1);
1434 gtk_grid_attach(GTK_GRID(right_vbox), ingame_votebar, 0, right_row++, 1, 1);
1435 gtk_grid_attach(GTK_GRID(hgrid), right_vbox, grid_col++, 0, 1, 1);
1436 } else {
1437 gtk_grid_attach(GTK_GRID(hgrid), top_notebook, grid_col++, 0, 1, 1);
1438 }
1439
1440 map_widget = gtk_grid_new();
1441
1442 mainbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
1443 gtk_box_append(GTK_BOX(mainbox), map_widget);
1444
1445 gtk_box_append(GTK_BOX(mainbox), editgui_get_editbar()->widget);
1446 ebar = editgui_get_editbar()->widget;
1447 gtk_widget_set_margin_bottom(ebar, 4);
1448 gtk_widget_set_margin_end(ebar, 4);
1449 gtk_widget_set_margin_start(ebar, 4);
1450 gtk_widget_set_margin_top(ebar, 4);
1451
1452 label = gtk_label_new(Q_("?noun:View"));
1453 gtk_notebook_append_page(GTK_NOTEBOOK(top_notebook), mainbox, label);
1454
1455 frame = gtk_frame_new(NULL);
1456 gtk_grid_attach(GTK_GRID(map_widget), frame, 0, 0, 1, 1);
1457
1458 map_canvas = gtk_drawing_area_new();
1459 gtk_widget_set_hexpand(map_canvas, TRUE);
1460 gtk_widget_set_vexpand(map_canvas, TRUE);
1461 gtk_widget_set_size_request(map_canvas, 300, 300);
1462 gtk_widget_set_can_focus(map_canvas, TRUE);
1463
1464 gtk_widget_set_focusable(map_canvas, TRUE);
1465
1466#if 0
1467 setup_canvas_color_for_state(GTK_STATE_FLAG_NORMAL);
1468 setup_canvas_color_for_state(GTK_STATE_FLAG_ACTIVE);
1469 setup_canvas_color_for_state(GTK_STATE_FLAG_PRELIGHT);
1470 setup_canvas_color_for_state(GTK_STATE_FLAG_SELECTED);
1471 setup_canvas_color_for_state(GTK_STATE_FLAG_INSENSITIVE);
1472 setup_canvas_color_for_state(GTK_STATE_FLAG_INCONSISTENT);
1473 setup_canvas_color_for_state(GTK_STATE_FLAG_FOCUSED);
1474 setup_canvas_color_for_state(GTK_STATE_FLAG_BACKDROP);
1475#endif /* 0 */
1476
1477 gtk_frame_set_child(GTK_FRAME(frame), map_canvas);
1478
1479 map_horizontal_scrollbar =
1480 gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL);
1481 gtk_grid_attach(GTK_GRID(map_widget), map_horizontal_scrollbar, 0, 1, 1, 1);
1482
1483 map_vertical_scrollbar =
1484 gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL);
1485 gtk_grid_attach(GTK_GRID(map_widget), map_vertical_scrollbar, 1, 0, 1, 1);
1486
1487 gtk_drawing_area_set_draw_func(GTK_DRAWING_AREA(map_canvas), map_canvas_draw,
1488 NULL, NULL);
1489
1490 mc_controller = GTK_EVENT_CONTROLLER(gtk_gesture_click_new());
1491 g_signal_connect(mc_controller, "pressed",
1492 G_CALLBACK(left_butt_down_mapcanvas), NULL);
1493 g_signal_connect(mc_controller, "released",
1494 G_CALLBACK(left_butt_up_mapcanvas), NULL);
1495 gtk_widget_add_controller(map_canvas, mc_controller);
1496 mc_gesture = gtk_gesture_click_new();
1497 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(mc_gesture), 3);
1498 mc_controller = GTK_EVENT_CONTROLLER(mc_gesture);
1499 g_signal_connect(mc_controller, "pressed",
1500 G_CALLBACK(right_butt_down_mapcanvas), NULL);
1501 g_signal_connect(mc_controller, "released",
1502 G_CALLBACK(right_butt_up_mapcanvas), NULL);
1503 gtk_widget_add_controller(map_canvas, mc_controller);
1504 mc_gesture = gtk_gesture_click_new();
1505 gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(mc_gesture), 2);
1506 mc_controller = GTK_EVENT_CONTROLLER(mc_gesture);
1507 g_signal_connect(mc_controller, "pressed",
1508 G_CALLBACK(middle_butt_down_mapcanvas), NULL);
1509 gtk_widget_add_controller(map_canvas, mc_controller);
1510 mc_controller = gtk_event_controller_scroll_new(GTK_EVENT_CONTROLLER_SCROLL_BOTH_AXES);
1511 g_signal_connect(mc_controller, "scroll",
1512 G_CALLBACK(mouse_scroll_mapcanvas), NULL);
1513 gtk_widget_add_controller(map_canvas, mc_controller);
1514 mc_controller = gtk_event_controller_motion_new();
1515 g_signal_connect(mc_controller, "motion",
1516 G_CALLBACK(move_mapcanvas), NULL);
1517 g_signal_connect(mc_controller, "leave",
1518 G_CALLBACK(leave_mapcanvas), NULL);
1519 gtk_widget_add_controller(map_canvas, mc_controller);
1520
1521 g_signal_connect(map_canvas, "resize",
1522 G_CALLBACK(map_canvas_resize), NULL);
1523
1524 mc_controller = gtk_event_controller_key_new();
1525 g_signal_connect(mc_controller, "key-pressed",
1526 G_CALLBACK(toplevel_key_press_handler), NULL);
1527 gtk_widget_add_controller(toplevel, mc_controller);
1528
1529 /* *** The message window -- this is a detachable widget *** */
1530
1531 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
1532 bottom_hpaned = paned;
1533 right_notebook = bottom_notebook = top_notebook;
1534 } else {
1535 GtkWidget *hpaned;
1536
1537 dtach_lowbox = detached_widget_new();
1538 gtk_paned_set_end_child(GTK_PANED(paned), dtach_lowbox);
1539 avbox = detached_widget_fill(dtach_lowbox);
1540
1541 mainbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
1542 if (!GUI_GTK_OPTION(small_display_layout)) {
1543 gtk_box_append(GTK_BOX(mainbox), ingame_votebar);
1544 }
1545 gtk_box_append(GTK_BOX(avbox), mainbox);
1546
1547 if (GUI_GTK_OPTION(small_display_layout)) {
1548 hpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1549 } else {
1550 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
1551 }
1552 gtk_box_append(GTK_BOX(mainbox), hpaned);
1553 gtk_widget_set_margin_bottom(hpaned, 4);
1554 gtk_widget_set_margin_end(hpaned, 4);
1555 gtk_widget_set_margin_start(hpaned, 4);
1556 gtk_widget_set_margin_top(hpaned, 4);
1557 bottom_hpaned = hpaned;
1558
1559 bottom_notebook = gtk_notebook_new();
1560 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(bottom_notebook), GTK_POS_TOP);
1561 gtk_notebook_set_scrollable(GTK_NOTEBOOK(bottom_notebook), TRUE);
1562 gtk_paned_set_start_child(GTK_PANED(hpaned), bottom_notebook);
1563
1564 right_notebook = gtk_notebook_new();
1565 g_object_ref(right_notebook);
1566 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(right_notebook), GTK_POS_TOP);
1567 gtk_notebook_set_scrollable(GTK_NOTEBOOK(right_notebook), TRUE);
1568 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_SPLIT) {
1569 gtk_paned_set_end_child(GTK_PANED(hpaned), right_notebook);
1570 }
1571 }
1572
1573 mainbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 2);
1574
1575 sw = gtk_scrolled_window_new();
1576 gtk_scrolled_window_set_has_frame(GTK_SCROLLED_WINDOW(sw),
1577 TRUE);
1578 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1579 GTK_POLICY_AUTOMATIC,
1580 GTK_POLICY_ALWAYS);
1581 gtk_box_append(GTK_BOX(mainbox), sw);
1582
1583 label = gtk_label_new(_("Chat"));
1584 gtk_notebook_append_page(GTK_NOTEBOOK(bottom_notebook), mainbox, label);
1585
1586 text = gtk_text_view_new_with_buffer(message_buffer);
1587 gtk_widget_set_hexpand(text, TRUE);
1588 gtk_widget_set_vexpand(text, TRUE);
1589 set_message_buffer_view_link_handlers(text);
1590 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
1591 gtk_scrolled_window_set_child(GTK_SCROLLED_WINDOW(sw), text);
1592
1593 gtk_widget_set_name(text, "chatline");
1594
1595 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
1596 gtk_widget_realize(text);
1597 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
1598
1599 main_message_area = GTK_TEXT_VIEW(text);
1600 if (dtach_lowbox != NULL) {
1601 g_object_set_data(G_OBJECT(dtach_lowbox), "hide-over-reparent", main_message_area);
1602 }
1603
1604 chat_welcome_message(TRUE);
1605
1606 /* The chat line */
1607 view = inputline_toolkit_view_new();
1608 gtk_box_append(GTK_BOX(mainbox), view);
1609 gtk_widget_set_margin_bottom(view, 3);
1610 gtk_widget_set_margin_end(view, 3);
1611 gtk_widget_set_margin_start(view, 3);
1612 gtk_widget_set_margin_top(view, 3);
1613
1614 button = gtk_check_button_new_with_label(_("Allies Only"));
1615 gtk_widget_set_focus_on_click(button, FALSE);
1616 gtk_check_button_set_active(GTK_CHECK_BUTTON(button),
1617 GUI_GTK_OPTION(allied_chat_only));
1618 g_signal_connect(button, "toggled",
1619 G_CALLBACK(allied_chat_button_toggled), NULL);
1620 inputline_toolkit_view_append_button(view, button);
1621 allied_chat_toggle_button = button;
1622
1623 button = gtk_button_new_with_label(_("Clear links"));
1624 g_signal_connect(button, "clicked",
1625 G_CALLBACK(link_marks_clear_all), NULL);
1626 inputline_toolkit_view_append_button(view, button);
1627
1628 /* Other things to take care of */
1629
1630 gtk_widget_set_visible(gtk_window_get_child(GTK_WINDOW(toplevel)),
1631 TRUE);
1632
1633 if (GUI_GTK_OPTION(enable_tabs)) {
1634 meswin_dialog_popup(FALSE);
1635 }
1636
1637 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 0);
1638 gtk_notebook_set_current_page(GTK_NOTEBOOK(bottom_notebook), 0);
1639
1640 if (!GUI_GTK_OPTION(map_scrollbars)) {
1641 gtk_widget_set_visible(map_horizontal_scrollbar, FALSE);
1642 gtk_widget_set_visible(map_vertical_scrollbar, FALSE);
1643 }
1644}
1645
1646/**********************************************************************/
1649 static void g_log_to_freelog_cb(const gchar *log_domain,
1650 GLogLevelFlags log_level,
1651 const gchar *message,
1652 gpointer user_data)
1653{
1654 enum log_level fllvl = LOG_ERROR;
1655
1656 switch (log_level) {
1657 case G_LOG_LEVEL_DEBUG:
1658 fllvl = LOG_DEBUG;
1659 break;
1660 case G_LOG_LEVEL_WARNING:
1661 fllvl = LOG_WARN;
1662 break;
1663 default:
1664 break;
1665 }
1666
1667 if (log_domain != NULL) {
1668 log_base(fllvl, "%s: %s", log_domain, message);
1669 } else {
1670 log_base(fllvl, "%s", message);
1671 }
1672}
1673
1674/**********************************************************************/
1677 static GLogWriterOutput g_log_writer_to_freelog_cb(GLogLevelFlags log_level,
1678 const GLogField *fields,
1679 gsize n_fields,
1680 gpointer user_data)
1681{
1682 /* No need to have formatter of our own - let's use glib's default one. */
1683 gchar *out = g_log_writer_format_fields(log_level, fields, n_fields, FALSE);
1684
1685 g_log_to_freelog_cb(NULL, log_level, out, NULL);
1686
1687 return G_LOG_WRITER_HANDLED;
1688}
1689
1690/**********************************************************************/
1693 static void set_g_log_callback_domain(const char *domain)
1694{
1695 g_log_set_handler(domain,
1696 G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_ERROR | G_LOG_LEVEL_WARNING
1697 | G_LOG_LEVEL_MASK
1698 | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
1699 g_log_to_freelog_cb, NULL);
1700}
1701
1702/**********************************************************************/
1705 static void set_g_log_callbacks(void)
1706{
1707 /* Old API, still used by many log producers */
1708 g_log_set_default_handler(g_log_to_freelog_cb, NULL);
1709
1710 set_g_log_callback_domain("Gtk");
1711 set_g_log_callback_domain("Gdk");
1712 set_g_log_callback_domain("Glib");
1713
1714 /* glib >= 2.50 API */
1715 g_log_set_writer_func(g_log_writer_to_freelog_cb, NULL, NULL);
1716}
1717
1718/**********************************************************************/
1721 void ui_init(void)
1722{
1723 log_set_callback(log_callback_utf8);
1724 set_g_log_callbacks();
1725 set_frame_by_frame_animation();
1726 zoom_phase_set(FALSE);
1727 zoom_set_steps(zoom_steps_custom);
1728}
1729
1730/**********************************************************************/
1733 int main(int argc, char **argv)
1734{
1735 return client_main(argc, argv, FALSE);
1736}
1737
1738/**********************************************************************/
1741 static void migrate_options_from_gtk2(void)
1742{
1743 log_normal(_("Migrating options from gtk2 to gtk3 client"));
1744
1745#define MIGRATE_OPTION(opt) gui_options.gui_gtk3_##opt = gui_options.gui_gtk2_##opt;
1746#define MIGRATE_STR_OPTION(opt) \
1747 strncpy(gui_options.gui_gtk3_##opt, gui_options.gui_gtk2_##opt, \
1748 sizeof(gui_options.gui_gtk3_##opt));
1749
1750 /* Default theme name is never migrated */
1751 /* 'fullscreen', 'small_display_layout', and 'message_chat_location'
1752 * not migrated, as (unlike Gtk2), Gtk3-client tries to pick better
1753 * defaults for these in fresh installations based on screen size (see
1754 * adjust_default_options()); so user is probably better served by
1755 * getting these adaptive defaults than whatever they had for Gtk2.
1756 * Since 'fullscreen' isn't migrated, we don't need to worry about
1757 * preserving gui_gtk2_migrated_from_2_5 either. */
1758 MIGRATE_OPTION(map_scrollbars);
1759 MIGRATE_OPTION(dialogs_on_top);
1760 MIGRATE_OPTION(show_task_icons);
1761 MIGRATE_OPTION(enable_tabs);
1762 MIGRATE_OPTION(show_chat_message_time);
1763 MIGRATE_OPTION(new_messages_go_to_top);
1764 MIGRATE_OPTION(show_message_window_buttons);
1765 MIGRATE_OPTION(metaserver_tab_first);
1766 MIGRATE_OPTION(allied_chat_only);
1767 MIGRATE_OPTION(mouse_over_map_focus);
1768 MIGRATE_OPTION(chatline_autocompletion);
1769 MIGRATE_OPTION(citydlg_xsize);
1770 MIGRATE_OPTION(citydlg_ysize);
1771 MIGRATE_OPTION(popup_tech_help);
1772
1773 MIGRATE_STR_OPTION(font_city_label);
1774 MIGRATE_STR_OPTION(font_notify_label);
1775 MIGRATE_STR_OPTION(font_spaceship_label);
1776 MIGRATE_STR_OPTION(font_help_label);
1777 MIGRATE_STR_OPTION(font_help_link);
1778 MIGRATE_STR_OPTION(font_help_text);
1779 MIGRATE_STR_OPTION(font_chatline);
1780 MIGRATE_STR_OPTION(font_beta_label);
1781 MIGRATE_STR_OPTION(font_small);
1782 MIGRATE_STR_OPTION(font_comment_label);
1783 MIGRATE_STR_OPTION(font_city_names);
1784 MIGRATE_STR_OPTION(font_city_productions);
1785 MIGRATE_STR_OPTION(font_reqtree_text);
1786
1787#undef MIGRATE_OPTION
1788#undef MIGRATE_STR_OPTION
1789
1790 gui_options.gui_gtk3_migrated_from_gtk2 = TRUE;
1791}
1792
1793/**********************************************************************/
1796 static void migrate_options_from_gtk3(void)
1797{
1798 log_normal(_("Migrating options from gtk3 to gtk3.22 client"));
1799
1800#define MIGRATE_OPTION(opt) gui_options.gui_gtk3_22_##opt = gui_options.gui_gtk3_##opt;
1801#define MIGRATE_STR_OPTION(opt) \
1802 strncpy(gui_options.gui_gtk3_22_##opt, gui_options.gui_gtk3_##opt, \
1803 sizeof(gui_options.gui_gtk3_22_##opt));
1804
1805 /* Default theme name is never migrated */
1806
1807 /* Simulate gui-gtk3's migrate_options_from_2_5() */
1808 if (!gui_options.gui_gtk3_migrated_from_2_5) {
1809 log_normal(_("Migrating gtk3-client options from freeciv-2.5 options."));
1810 gui_options.gui_gtk3_fullscreen = gui_options.migrate_fullscreen;
1811 gui_options.gui_gtk3_migrated_from_2_5 = TRUE;
1812 }
1813
1814 MIGRATE_OPTION(fullscreen);
1815 MIGRATE_OPTION(map_scrollbars);
1816 MIGRATE_OPTION(dialogs_on_top);
1817 MIGRATE_OPTION(show_task_icons);
1818 MIGRATE_OPTION(enable_tabs);
1819 MIGRATE_OPTION(show_chat_message_time);
1820 MIGRATE_OPTION(new_messages_go_to_top);
1821 MIGRATE_OPTION(show_message_window_buttons);
1822 MIGRATE_OPTION(metaserver_tab_first);
1823 MIGRATE_OPTION(allied_chat_only);
1824 MIGRATE_OPTION(message_chat_location);
1825 MIGRATE_OPTION(small_display_layout);
1826 MIGRATE_OPTION(mouse_over_map_focus);
1827 MIGRATE_OPTION(chatline_autocompletion);
1828 MIGRATE_OPTION(citydlg_xsize);
1829 MIGRATE_OPTION(citydlg_ysize);
1830 MIGRATE_OPTION(popup_tech_help);
1831
1832 MIGRATE_STR_OPTION(font_city_label);
1833 MIGRATE_STR_OPTION(font_notify_label);
1834 MIGRATE_STR_OPTION(font_spaceship_label);
1835 MIGRATE_STR_OPTION(font_help_label);
1836 MIGRATE_STR_OPTION(font_help_link);
1837 MIGRATE_STR_OPTION(font_help_text);
1838 MIGRATE_STR_OPTION(font_chatline);
1839 MIGRATE_STR_OPTION(font_beta_label);
1840 MIGRATE_STR_OPTION(font_small);
1841 MIGRATE_STR_OPTION(font_comment_label);
1842 MIGRATE_STR_OPTION(font_city_names);
1843 MIGRATE_STR_OPTION(font_city_productions);
1844 MIGRATE_STR_OPTION(font_reqtree_text);
1845
1846#undef MIGRATE_OPTION
1847#undef MIGRATE_STR_OPTION
1848
1849 gui_options.gui_gtk3_22_migrated_from_gtk3 = TRUE;
1850}
1851
1852/**********************************************************************/
1855 static void migrate_options_from_gtk3_22(void)
1856{
1857 log_normal(_("Migrating options from gtk3.22 to gtk4 client"));
1858
1859#define MIGRATE_OPTION(opt) GUI_GTK_OPTION(opt) = gui_options.gui_gtk3_22_##opt;
1860#define MIGRATE_STR_OPTION(opt) \
1861 strncpy(GUI_GTK_OPTION(opt), gui_options.gui_gtk3_22_##opt, \
1862 sizeof(GUI_GTK_OPTION(opt)));
1863
1864 /* Default theme name is never migrated */
1865 MIGRATE_OPTION(fullscreen);
1866 MIGRATE_OPTION(map_scrollbars);
1867 MIGRATE_OPTION(dialogs_on_top);
1868 MIGRATE_OPTION(show_task_icons);
1869 MIGRATE_OPTION(enable_tabs);
1870 MIGRATE_OPTION(show_chat_message_time);
1871 MIGRATE_OPTION(new_messages_go_to_top);
1872 MIGRATE_OPTION(show_message_window_buttons);
1873 MIGRATE_OPTION(metaserver_tab_first);
1874 MIGRATE_OPTION(allied_chat_only);
1875 MIGRATE_OPTION(message_chat_location);
1876 MIGRATE_OPTION(small_display_layout);
1877 MIGRATE_OPTION(mouse_over_map_focus);
1878 MIGRATE_OPTION(chatline_autocompletion);
1879 MIGRATE_OPTION(citydlg_xsize);
1880 MIGRATE_OPTION(citydlg_ysize);
1881 MIGRATE_OPTION(popup_tech_help);
1882
1883 MIGRATE_STR_OPTION(font_city_label);
1884 MIGRATE_STR_OPTION(font_notify_label);
1885 MIGRATE_STR_OPTION(font_spaceship_label);
1886 MIGRATE_STR_OPTION(font_help_label);
1887 MIGRATE_STR_OPTION(font_help_link);
1888 MIGRATE_STR_OPTION(font_help_text);
1889 MIGRATE_STR_OPTION(font_chatline);
1890 MIGRATE_STR_OPTION(font_beta_label);
1891 MIGRATE_STR_OPTION(font_small);
1892 MIGRATE_STR_OPTION(font_comment_label);
1893 MIGRATE_STR_OPTION(font_city_names);
1894 MIGRATE_STR_OPTION(font_city_productions);
1895 MIGRATE_STR_OPTION(font_reqtree_text);
1896
1897#undef MIGRATE_OPTION
1898#undef MIGRATE_STR_OPTION
1899
1900 GUI_GTK_OPTION(migrated_from_gtk3_22) = TRUE;
1901}
1902
1903/**********************************************************************/
1906 int ui_main(int argc, char **argv)
1907{
1908 if (parse_options(argc, argv)) {
1909 /* The locale has already been set in init_nls() and the windows-specific
1910 * locale logic in gtk_init() causes problems with zh_CN (see PR#39475) */
1911 gtk_disable_setlocale();
1912
1913 if (!gtk_init_check()) {
1914 log_fatal(_("Failed to open graphical mode."));
1915 return EXIT_FAILURE;
1916 }
1917
1918 menus_set_initial_toggle_values();
1919
1920 gui_up = TRUE;
1921 fc_app = gtk_application_new(NULL, 0);
1922 g_signal_connect(fc_app, "activate", G_CALLBACK(activate_gui), NULL);
1923 g_application_run(G_APPLICATION(fc_app), 0, NULL);
1924 gui_up = FALSE;
1925
1926 destroy_server_scans();
1927 free_mapcanvas_and_overview();
1928 spaceship_dialog_done();
1929 intel_dialog_done();
1930 citizens_dialog_done();
1931 luaconsole_dialog_done();
1932 happiness_dialog_done();
1933 diplomacy_dialog_done();
1934 cma_fe_done();
1935 free_unit_table();
1936
1937 /* We have extra ref for unit_info_box that has protected
1938 * it from getting destroyed when editinfobox_refresh()
1939 * moves widgets around. Free that extra ref here. */
1940 g_object_unref(unit_info_box);
1941 if (empty_unit_paintable != NULL) {
1942 g_object_unref(empty_unit_paintable);
1943 }
1944
1945 editgui_free();
1946 gtk_window_destroy(GTK_WINDOW(toplevel));
1947 message_buffer = NULL; /* Result of destruction of everything */
1948 tileset_free_tiles(tileset);
1949 }
1950
1951 return EXIT_SUCCESS;
1952}
1953
1954/**********************************************************************/
1957 static void activate_gui(GtkApplication *app, gpointer data)
1958{
1959 PangoFontDescription *toplevel_font_name;
1960 guint sig;
1961 GtkEventController *controller;
1962 char window_name[1024];
1963
1964 toplevel = gtk_application_window_new(app);
1965 if (vmode.width > 0 && vmode.height > 0) {
1966 gtk_window_set_default_size(GTK_WINDOW(toplevel),
1967 vmode.width, vmode.height);
1968 }
1969
1970 controller = GTK_EVENT_CONTROLLER(gtk_event_controller_focus_new());
1971 g_signal_connect(controller, "enter",
1972 G_CALLBACK(fc_gained_focus), NULL);
1973 g_signal_connect(controller, "leave",
1974 G_CALLBACK(fc_lost_focus), NULL);
1975 gtk_widget_add_controller(toplevel, controller);
1976
1977 gtk_widget_realize(toplevel);
1978 gtk_widget_set_name(toplevel, "Freeciv");
1979
1980 help_system_init();
1981
1982 dlg_tab_provider_prepare();
1983
1984 if (gui_options.first_boot) {
1985 adjust_default_options();
1986 /* We're using fresh defaults for this version of this client,
1987 * so prevent any future migrations from other clients / versions */
1988 GUI_GTK_OPTION(migrated_from_gtk3_22) = TRUE;
1989 /* Avoid also marking previous Gtk clients as migrated, so that
1990 * they can have their own run of their adjust_default_options() if
1991 * they are ever run (as a side effect of Gtk2->Gtk3 migration). */
1992 } else {
1993 if (!GUI_GTK_OPTION(migrated_from_gtk3_22)) {
1994 if (!gui_options.gui_gtk3_22_migrated_from_gtk3) {
1995 if (!gui_options.gui_gtk3_migrated_from_gtk2) {
1996 migrate_options_from_gtk2();
1997 /* We want a fresh look at screen-size-related options after Gtk2 */
1998 adjust_default_options();
1999 /* We don't ever want to consider pre-2.6 fullscreen option again
2000 * (even for gui-gtk3) */
2001 gui_options.gui_gtk3_migrated_from_2_5 = TRUE;
2002 }
2003 migrate_options_from_gtk3();
2004 }
2005 migrate_options_from_gtk3_22();
2006 }
2007 }
2008
2009 if (GUI_GTK_OPTION(fullscreen)) {
2010 gtk_window_fullscreen(GTK_WINDOW(toplevel));
2011 }
2012
2013 fc_snprintf(window_name, sizeof(window_name), _("Freeciv (%s)"), GUI_NAME_SHORT);
2014 gtk_window_set_title(GTK_WINDOW(toplevel), window_name);
2015
2016 g_signal_connect(toplevel, "close-request",
2017 G_CALLBACK(quit_dialog_callback), NULL);
2018
2019 /* Disable GTK cursor key focus movement */
2020 sig = g_signal_lookup("move-focus", GTK_TYPE_WIDGET);
2021 g_signal_handlers_disconnect_matched(toplevel, G_SIGNAL_MATCH_ID, sig,
2022 0, 0, 0, 0);
2023 g_signal_connect(toplevel, "move-focus", G_CALLBACK(toplevel_focus), NULL);
2024
2025 options_iterate(client_optset, poption) {
2026 if (OT_FONT == option_type(poption)) {
2027 /* Force to call the appropriate callback. */
2028 option_changed(poption);
2029 }
2030 } options_iterate_end;
2031
2032 toplevel_font_name = pango_context_get_font_description(
2033 gtk_widget_get_pango_context(toplevel));
2034
2035 if (NULL == city_names_style) {
2036 city_names_style = pango_font_description_copy(toplevel_font_name);
2037 log_error("city_names_style should have been set by options.");
2038 }
2039 if (NULL == city_productions_style) {
2040 city_productions_style = pango_font_description_copy(toplevel_font_name);
2041 log_error("city_productions_style should have been set by options.");
2042 }
2043 if (NULL == reqtree_text_style) {
2044 reqtree_text_style = pango_font_description_copy(toplevel_font_name);
2045 log_error("reqtree_text_style should have been set by options.");
2046 }
2047
2048 tileset_init(tileset);
2049 tileset_load_tiles(tileset);
2050
2051 /* Keep the icon of the executable on Windows (see PR#36491) */
2052#ifndef FREECIV_MSWINDOWS
2053 {
2054 /* Only call this after tileset_load_tiles is called. */
2055 gtk_window_set_icon_name(GTK_WINDOW(toplevel), "freeciv");
2056 }
2057#endif /* FREECIV_MSWINDOWS */
2058
2059 setup_widgets();
2060 load_cursors();
2061 cma_fe_init();
2062 diplomacy_dialog_init();
2063 luaconsole_dialog_init();
2064 happiness_dialog_init();
2065 citizens_dialog_init();
2066 intel_dialog_init();
2067 spaceship_dialog_init();
2068 chatline_init();
2069 init_mapcanvas_and_overview();
2070
2071 tileset_use_preferred_theme(tileset);
2072
2073 gtk_widget_set_visible(toplevel, TRUE);
2074
2075 /* Assumes toplevel showing */
2076 set_client_state(C_S_DISCONNECTED);
2077
2078 /* Assumes client_state is set */
2079 timer_id = g_timeout_add(TIMER_INTERVAL, timer_callback, NULL);
2080}
2081
2082/**********************************************************************/
2085 bool is_gui_up(void)
2086{
2087 return gui_up;
2088}
2089
2090/**********************************************************************/
2093 void ui_exit(void)
2094{
2095 if (message_buffer != NULL) {
2096 g_object_unref(message_buffer);
2097 message_buffer = NULL;
2098 }
2099}
2100
2101/**********************************************************************/
2104 enum gui_type get_gui_type(void)
2105{
2106 return GUI_GTK4;
2107}
2108
2109/**********************************************************************/
2112 void sound_bell(void)
2113{
2114 gdk_display_beep(gdk_display_get_default());
2115}
2116
2117/**********************************************************************/
2123 void set_unit_icon(int idx, struct unit *punit)
2124{
2125 GtkWidget *w;
2126
2127 fc_assert_ret(idx >= -1 && idx < num_units_below);
2128
2129 if (idx == -1) {
2130 w = unit_pic;
2131 unit_id_top = punit ? punit->id : 0;
2132 } else {
2133 w = unit_below_pic[idx];
2134 unit_ids[idx] = punit ? punit->id : 0;
2135 }
2136
2137 if (!w) {
2138 return;
2139 }
2140
2141 if (punit) {
2142 put_unit_picture(punit, GTK_PICTURE(w), -1);
2143 } else {
2144 if (empty_unit_paintable == NULL) {
2145 /* FIXME: Use proper icon height instead of hardcoded 50 */
2146 empty_unit_paintable = gdk_paintable_new_empty(tileset_tile_width(tileset), 50);
2147
2148 /* Add ref to avoid it getting destroyed along any single parent widget. */
2149 g_object_ref(empty_unit_paintable);
2150 }
2151 gtk_picture_set_paintable(GTK_PICTURE(w), empty_unit_paintable);
2152 }
2153}
2154
2155/**********************************************************************/
2160 void set_unit_icons_more_arrow(bool onoff)
2161{
2162 static bool showing = FALSE;
2163
2164 if (more_arrow == nullptr) {
2165 return;
2166 }
2167
2168 if (onoff && !showing) {
2169 gtk_widget_set_visible(more_arrow, TRUE);
2170 showing = TRUE;
2171 } else if (!onoff && showing) {
2172 gtk_widget_set_visible(more_arrow, FALSE);
2173 showing = FALSE;
2174 }
2175}
2176
2177/**********************************************************************/
2183 void real_focus_units_changed(void)
2184{
2185 goto_dialog_focus_units_changed();
2186}
2187
2188/**********************************************************************/
2192 static gboolean select_unit_pic_callback(GtkGestureClick *gesture, int n_press,
2193 double x, double y, gpointer data)
2194{
2195 int i = GPOINTER_TO_INT(data);
2196 struct unit *punit;
2197
2198 if (i == -1) {
2199 punit = game_unit_by_number(unit_id_top);
2200 if (punit && unit_is_in_focus(punit)) {
2201 /* Clicking on the currently selected unit will center it. */
2202 center_tile_mapcanvas(unit_tile(punit));
2203 }
2204 return TRUE;
2205 }
2206
2207 if (unit_ids[i] == 0) { /* No unit displayed at this place */
2208 return TRUE;
2209 }
2210
2211 punit = game_unit_by_number(unit_ids[i]);
2212 if (NULL != punit && unit_owner(punit) == client_player()) {
2213 /* Unit shouldn't be NULL but may be owned by an ally. */
2214 unit_focus_set(punit);
2215 }
2216
2217 return TRUE;
2218}
2219
2220/**********************************************************************/
2224 static gboolean select_more_arrow_callback(GtkGestureClick *gesture, int n_press,
2225 double x, double y, gpointer data)
2226{
2227 struct unit *punit = game_unit_by_number(unit_id_top);
2228
2229 if (punit) {
2230 unit_select_dialog_popup(unit_tile(punit));
2231 }
2232
2233 return TRUE;
2234}
2235
2236/**********************************************************************/
2239 static void info_popup_closed(GtkWidget *self, gpointer data)
2240{
2241 gtk_widget_unparent(self);
2242}
2243
2244/**********************************************************************/
2247 static gboolean show_info_popup(GtkGestureClick *gesture, int n_press,
2248 double x, double y, gpointer data)
2249{
2250 GtkWidget *p;
2251 GtkWidget *child;
2252 GtkWidget *frame = GTK_WIDGET(data);
2253
2254 p = gtk_popover_new();
2255
2256 gtk_widget_set_parent(p, frame);
2257 child = gtk_label_new(get_info_label_text_popup());
2258 gtk_popover_set_child(GTK_POPOVER(p), child);
2259 g_signal_connect(p, "closed",
2260 G_CALLBACK(info_popup_closed), NULL);
2261 gtk_popover_popup(GTK_POPOVER(p));
2262
2263 return TRUE;
2264}
2265
2266/**********************************************************************/
2269 static void end_turn_callback(GtkWidget *w, gpointer data)
2270{
2271 gtk_widget_set_sensitive(turn_done_button, FALSE);
2272 user_ended_turn();
2273}
2274
2275/**********************************************************************/
2278 static gboolean get_net_input(GIOChannel *source, GIOCondition condition,
2279 gpointer data)
2280{
2281 input_from_server(g_io_channel_unix_get_fd(source));
2282
2283 return TRUE;
2284}
2285
2286/**********************************************************************/
2289 static void set_wait_for_writable_socket(struct connection *pc,
2290 bool socket_writable)
2291{
2292 static bool previous_state = FALSE;
2293
2294 fc_assert_ret(pc == &client.conn);
2295
2296 if (previous_state == socket_writable)
2297 return;
2298
2299 log_debug("set_wait_for_writable_socket(%d)", socket_writable);
2300
2301 g_source_remove(srv_id);
2302 srv_id = g_io_add_watch(srv_channel,
2303 G_IO_IN | (socket_writable ? G_IO_OUT : 0) | G_IO_ERR,
2304 get_net_input,
2305 NULL);
2306
2307 previous_state = socket_writable;
2308}
2309
2310/**********************************************************************/
2314 void add_net_input(int sock)
2315{
2316#ifdef FREECIV_MSWINDOWS
2317 srv_channel = g_io_channel_win32_new_socket(sock);
2318#else
2319 srv_channel = g_io_channel_unix_new(sock);
2320#endif
2321 srv_id = g_io_add_watch(srv_channel,
2322 G_IO_IN | G_IO_ERR,
2323 get_net_input,
2324 NULL);
2325 client.conn.notify_of_writable_data = set_wait_for_writable_socket;
2326}
2327
2328/**********************************************************************/
2332 void remove_net_input(void)
2333{
2334 g_source_remove(srv_id);
2335 g_io_channel_unref(srv_channel);
2336 gtk_widget_set_cursor(toplevel, NULL);
2337}
2338
2339/**********************************************************************/
2343 static void quit_dialog_response(GtkWidget *dialog, gint response)
2344{
2345 gtk_window_destroy(GTK_WINDOW(dialog));
2346 if (response == GTK_RESPONSE_YES) {
2347 start_quitting();
2348 if (client.conn.used) {
2349 disconnect_from_server(FALSE);
2350 }
2351 quit_gtk_main();
2352 }
2353}
2354
2355/**********************************************************************/
2358 void quit_gtk_main(void)
2359{
2360 /* Quit gtk main loop. After this it will return to finish
2361 * ui_main() */
2362
2363 g_application_quit(G_APPLICATION(fc_app));
2364}
2365
2366/**********************************************************************/
2370 void popup_quit_dialog(void)
2371{
2372 static GtkWidget *dialog;
2373
2374 if (!dialog) {
2375 dialog = gtk_message_dialog_new(NULL,
2376 0,
2377 GTK_MESSAGE_WARNING,
2378 GTK_BUTTONS_YES_NO,
2379 _("Are you sure you want to quit?"));
2380 setup_dialog(dialog, toplevel);
2381
2382 g_signal_connect(dialog, "response",
2383 G_CALLBACK(quit_dialog_response), NULL);
2384 g_signal_connect(dialog, "destroy",
2385 G_CALLBACK(widget_destroyed), &dialog);
2386 }
2387
2388 gtk_window_present(GTK_WINDOW(dialog));
2389}
2390
2391/**********************************************************************/
2394 static gboolean quit_dialog_callback(void)
2395{
2396 popup_quit_dialog();
2397 /* Stop emission of event. */
2398 return TRUE;
2399}
2400
2401struct callback {
2402 void (*callback)(void *data);
2403 void *data;
2404};
2405
2406/**********************************************************************/
2409 static gboolean idle_callback_wrapper(gpointer data)
2410{
2411 struct callback *cb = data;
2412
2413 (cb->callback)(cb->data);
2414 free(cb);
2415
2416 return FALSE;
2417}
2418
2419/**********************************************************************/
2424 void add_idle_callback(void (callback)(void *), void *data)
2425{
2426 struct callback *cb = fc_malloc(sizeof(*cb));
2427
2428 cb->callback = callback;
2429 cb->data = data;
2430 g_idle_add(idle_callback_wrapper, cb);
2431}
2432
2433/**********************************************************************/
2436 void animation_idle_cb(void *data)
2437{
2438 if (get_current_client_page() == PAGE_GAME) {
2439 update_animation();
2440 add_idle_callback(animation_idle_cb, NULL);
2441 }
2442}
2443
2444/**********************************************************************/
2448 static void allied_chat_only_callback(struct option *poption)
2449{
2450 GtkWidget *button;
2451
2452 button = allied_chat_toggle_button;
2453 fc_assert_ret(button != NULL);
2454 fc_assert_ret(GTK_IS_CHECK_BUTTON(button));
2455
2456 gtk_check_button_set_active(GTK_CHECK_BUTTON(button),
2457 option_bool_get(poption));
2458}
2459
2460/**********************************************************************/
2463 void fullscreen_opt_refresh(struct option *poption)
2464{
2465 if (GUI_GTK_OPTION(fullscreen)) {
2466 gtk_window_fullscreen(GTK_WINDOW(toplevel));
2467 } else {
2468 gtk_window_unfullscreen(GTK_WINDOW(toplevel));
2469 }
2470}
2471
2472/**********************************************************************/
2475 static void apply_city_names_font(struct option *poption)
2476{
2477 gui_update_font_full(option_font_target(poption),
2478 option_font_get(poption),
2479 &city_names_style);
2480 update_city_descriptions();
2481}
2482
2483/**********************************************************************/
2486 static void apply_city_productions_font(struct option *poption)
2487{
2488 gui_update_font_full(option_font_target(poption),
2489 option_font_get(poption),
2490 &city_productions_style);
2491 update_city_descriptions();
2492}
2493
2494/**********************************************************************/
2497 static void apply_reqtree_text_font(struct option *poption)
2498{
2499 gui_update_font_full(option_font_target(poption),
2500 option_font_get(poption),
2501 &reqtree_text_style);
2502 science_report_dialog_redraw();
2503}
2504
2505/**********************************************************************/
2509 void options_extra_init(void)
2510{
2511 struct option *poption;
2512
2513#define option_var_set_callback(var, callback) \
2514 if ((poption = optset_option_by_name(client_optset, \
2515 GUI_GTK_OPTION_STR(var)))) { \
2516 option_set_changed_callback(poption, callback); \
2517 } else { \
2518 log_error("Didn't find option %s!", GUI_GTK_OPTION_STR(var)); \
2519 }
2520
2521 option_var_set_callback(allied_chat_only,
2522 allied_chat_only_callback);
2523 option_var_set_callback(fullscreen,
2524 fullscreen_opt_refresh);
2525
2526 option_var_set_callback(font_city_names,
2527 apply_city_names_font);
2528 option_var_set_callback(font_city_productions,
2529 apply_city_productions_font);
2530 option_var_set_callback(font_reqtree_text,
2531 apply_reqtree_text_font);
2532#undef option_var_set_callback
2533}
2534
2535/**********************************************************************/
2539 void refresh_chat_buttons(void)
2540{
2541 GtkWidget *button;
2542
2543 button = allied_chat_toggle_button;
2544 fc_assert_ret(button != nullptr);
2545 fc_assert_ret(GTK_IS_CHECK_BUTTON(button));
2546
2547 /* Hide the "Allies Only" button for local games. */
2548 if (is_server_running()) {
2549 gtk_widget_set_visible(button, FALSE);
2550 } else {
2551 gtk_widget_set_visible(button, TRUE);
2552 gtk_check_button_set_active(GTK_CHECK_BUTTON(button),
2553 GUI_GTK_OPTION(allied_chat_only));
2554 }
2555}
2556
2557/**********************************************************************/
2560 static void allied_chat_button_toggled(GtkToggleButton *button,
2561 gpointer user_data)
2562{
2563 GUI_GTK_OPTION(allied_chat_only) = gtk_toggle_button_get_active(button);
2564}
2565
2566/**********************************************************************/
2569 void insert_client_build_info(char *outbuf, size_t outlen)
2570{
2571 cat_snprintf(outbuf, outlen, _("\nBuilt against gtk %d.%d.%d, using %d.%d.%d"
2572 "\nBuilt against glib %d.%d.%d, using %d.%d.%d"),
2573 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION,
2574 gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version(),
2575 GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
2576 glib_major_version, glib_minor_version, glib_micro_version);
2577}
2578
2579/**********************************************************************/
2583 static bool monitor_size(GdkRectangle *rect_p)
2584{
2585 GdkDisplay *display;
2586 GdkMonitor *monitor;
2587
2588 display = gdk_display_get_default();
2589 if (!display) {
2590 return FALSE;
2591 }
2592
2593 monitor = g_list_model_get_item(gdk_display_get_monitors(display), 0);
2594
2595 if (!monitor) {
2596 return FALSE;
2597 }
2598
2599 gdk_monitor_get_geometry(monitor, rect_p);
2600
2601 return TRUE;
2602}
2603
2604/**********************************************************************/
2607 int screen_width(void)
2608{
2609 GdkRectangle rect;
2610
2611 if (vmode.width > 0) {
2612 return vmode.width;
2613 }
2614
2615 if (monitor_size(&rect)) {
2616 return rect.width;
2617 } else {
2618 return 0;
2619 }
2620}
2621
2622/**********************************************************************/
2625 int screen_height(void)
2626{
2627 GdkRectangle rect;
2628
2629 if (vmode.height > 0) {
2630 return vmode.height;
2631 }
2632
2633 if (monitor_size(&rect)) {
2634 return rect.height;
2635 } else {
2636 return 0;
2637 }
2638}
2639
2640/**********************************************************************/
2643 struct video_mode *resolution_request_get(void)
2644{
2645 if (vmode.width > 0 && vmode.height > 0) {
2646 return &vmode;
2647 }
2648
2649 return NULL;
2650}
2651
2652/**********************************************************************/
2655 static void adjust_default_options(void)
2656{
2657 int scr_height = screen_height();
2658
2659 if (scr_height > 0) {
2660 /* Adjust these options only if we do know the screen height. */
2661
2662 if (scr_height <= 480) {
2663 /* Freeciv is practically unusable outside fullscreen mode in so
2664 * small display */
2665 log_verbose("Changing default to fullscreen due to very small screen");
2666 GUI_GTK_OPTION(fullscreen) = TRUE;
2667 }
2668 if (scr_height < 1024) {
2669 /* This is a small display */
2670 log_verbose("Defaulting to small widget layout due to small screen");
2671 GUI_GTK_OPTION(small_display_layout) = TRUE;
2672 log_verbose("Defaulting to merged messages/chat due to small screen");
2673 GUI_GTK_OPTION(message_chat_location) = GUI_GTK_MSGCHAT_MERGED;
2674 }
2675 }
2676}
2677
2678/**********************************************************************/
2681 GtkApplication *gui_app(void)
2682{
2683 return fc_app;
2684}
audio_pause
void audio_pause(void)
Definition audio.c:606
audio_resume
void audio_resume(void)
Definition audio.c:614
audio.h
height
struct canvas int int struct sprite int int int int height
Definition canvas_g.h:44
width
struct canvas int int struct sprite int int int width
Definition canvas_g.h:44
chat_welcome_message
void chat_welcome_message(bool gui_has_copying_mitem)
Definition chatline_common.c:177
self
static struct ai_type * self
Definition classicai.c:46
client_is_observer
bool client_is_observer(void)
Definition client_main.c:1083
real_timer_callback
double real_timer_callback(void)
Definition client_main.c:1182
client_main
int client_main(int argc, char *argv[], bool postpone_tileset)
Definition client_main.c:351
user_ended_turn
void user_ended_turn(void)
Definition client_main.c:798
client
struct civclient client
Definition client_main.c:150
start_quitting
void start_quitting(void)
Definition client_main.c:1644
set_client_state
void set_client_state(enum client_states newstate)
Definition client_main.c:844
can_client_change_view
bool can_client_change_view(void)
Definition client_main.c:1312
client_main.h
client_player
#define client_player()
Definition client_main.h:106
TIMER_INTERVAL
#define TIMER_INTERVAL
Definition client_main.h:30
C_S_DISCONNECTED
@ C_S_DISCONNECTED
Definition client_main.h:45
buy_production_in_selected_cities
void buy_production_in_selected_cities(void)
Definition climisc.c:1306
client_warming_sprite
struct sprite * client_warming_sprite(void)
Definition climisc.c:377
client_cooling_sprite
struct sprite * client_cooling_sprite(void)
Definition climisc.c:394
client_research_sprite
struct sprite * client_research_sprite(void)
Definition climisc.c:354
client_government_sprite
struct sprite * client_government_sprite(void)
Definition climisc.c:412
climisc.h
disconnect_from_server
void disconnect_from_server(bool leaving_sound)
Definition clinet.c:306
input_from_server
void input_from_server(int fd)
Definition clinet.c:411
clinet.h
get_color
struct color * get_color(const struct tileset *t, enum color_std stdcolor)
Definition colors_common.c:100
incite_cost
char * incite_cost
Definition comments.c:74
is_server_running
bool is_server_running(void)
Definition connectdlg_common.c:124
connectdlg_common.h
key_recall_previous_focus_unit
void key_recall_previous_focus_unit(void)
Definition control.c:3291
unit_is_in_focus
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:383
key_cancel_action
void key_cancel_action(void)
Definition control.c:3229
num_units_below
int num_units_below
Definition control.c:76
unit_focus_set
void unit_focus_set(struct unit *punit)
Definition control.c:501
get_units_in_focus
struct unit_list * get_units_in_focus(void)
Definition control.c:177
key_end_turn
void key_end_turn(void)
Definition control.c:3283
update_unit_pix_label
void update_unit_pix_label(struct unit_list *punitlist)
Definition control.c:967
key_unit_move
void key_unit_move(enum direction8 gui_dir)
Definition control.c:3312
hover_state
enum cursor_hover_state hover_state
Definition control.c:89
head_of_units_in_focus
struct unit * head_of_units_in_focus(void)
Definition control.c:405
get_num_units_in_focus
int get_num_units_in_focus(void)
Definition control.c:185
control_mouse_cursor
void control_mouse_cursor(struct tile *ptile)
Definition control.c:1189
key_center_capital
void key_center_capital(void)
Definition control.c:3266
control.h
MAX_NUM_UNITS_BELOW
#define MAX_NUM_UNITS_BELOW
Definition control.h:295
HOVER_NONE
@ HOVER_NONE
Definition control.h:26
dataio.h
punit
struct unit struct city struct unit struct tile struct extra_type const struct act_prob *act_probs int actor_unit_id struct unit struct unit * punit
Definition dialogs_g.h:74
editor_is_active
bool editor_is_active(void)
Definition editor.c:346
editor.h
is_option
bool is_option(const char *option_name, char *option)
Definition fc_cmdline.c:112
get_option_malloc
char * get_option_malloc(const char *option_name, char **argv, int *i, int argc, bool gc)
Definition fc_cmdline.c:50
fc_cmdline.h
O_SCIENCE
@ O_SCIENCE
Definition fc_types.h:101
O_GOLD
@ O_GOLD
Definition fc_types.h:101
fciconv.h
fc_fprintf
void fc_fprintf(FILE *stream, const char *format,...) fc__attribute((__format__(__printf__
fcintl.h
Q_
#define Q_(String)
Definition fcintl.h:70
_
#define _(String)
Definition fcintl.h:67
featured_text.h
game_unit_by_number
struct unit * game_unit_by_number(int id)
Definition game.c:116
game.h
government.h
inputline_has_focus
bool inputline_has_focus(void)
Definition chatline.c:72
inputline_toolkit_view_append_button
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1293
inputline_toolkit_view_new
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1271
set_message_buffer_view_link_handlers
void set_message_buffer_view_link_handlers(GtkWidget *view)
Definition chatline.c:745
inputline_is_visible
bool inputline_is_visible(void)
Definition chatline.c:88
chatline_init
void chatline_init(void)
Definition chatline.c:1303
inputline_grab_focus
void inputline_grab_focus(void)
Definition chatline.c:80
chatline_scroll_to_bottom
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1007
citizens_dialog_init
void citizens_dialog_init(void)
Definition citizensinfo.c:269
citizens_dialog_done
void citizens_dialog_done(void)
Definition citizensinfo.c:277
cma_fe_init
void cma_fe_init(void)
Definition cma_fe.c:88
cma_fe_done
void cma_fe_done(void)
Definition cma_fe.c:96
unit_select_dialog_popup
void unit_select_dialog_popup(struct tile *ptile)
Definition dialogs.c:377
taxrates_callback
gboolean taxrates_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition dialogs.c:1425
diplomacy_dialog_init
void diplomacy_dialog_init(void)
Definition diplodlg.c:1204
diplomacy_dialog_done
void diplomacy_dialog_done(void)
Definition diplodlg.c:1213
handle_edit_key_press
gboolean handle_edit_key_press(GdkEventKey *ev)
Definition editgui.c:1662
editgui_create_widgets
void editgui_create_widgets(void)
Definition editgui.c:1822
editgui_get_editbar
struct editbar * editgui_get_editbar(void)
Definition editgui.c:1788
editgui_free
void editgui_free(void)
Definition editgui.c:1835
goto_dialog_focus_units_changed
void goto_dialog_focus_units_changed(void)
Definition gotodlg.c:541
source
static GtkWidget * source
Definition gotodlg.c:58
load_cursors
void load_cursors(void)
Definition graphics.c:84
map_vertical_scrollbar
GtkWidget * map_vertical_scrollbar
Definition gui_main.c:109
ui_main
int ui_main(int argc, char **argv)
Definition gui_main.c:1909
client_string
const char * client_string
Definition gui_main.c:105
message_buffer
GtkTextBuffer * message_buffer
Definition gui_main.c:178
quit_dialog_response
static void quit_dialog_response(GtkWidget *dialog, gint response)
Definition gui_main.c:2344
real_focus_units_changed
void real_focus_units_changed(void)
Definition gui_main.c:2171
set_unit_icons_more_arrow
void set_unit_icons_more_arrow(bool onoff)
Definition gui_main.c:2148
print_usage
static void print_usage(void)
Definition gui_main.c:265
OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK
#define OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK
Definition gui_main.c:116
option_var_set_callback
#define option_var_set_callback(var, callback)
quit_dialog_callback
static gboolean quit_dialog_callback(void)
Definition gui_main.c:2397
srv_channel
static GIOChannel * srv_channel
Definition gui_main.c:182
main_label_info
GtkWidget * main_label_info
Definition gui_main.c:138
monitor_size
static bool monitor_size(GdkRectangle *rect_p)
Definition gui_main.c:2575
bottom_notebook
GtkWidget * bottom_notebook
Definition gui_main.c:129
unit_info_label
GtkWidget * unit_info_label
Definition gui_main.c:151
timer_callback
static gboolean timer_callback(gpointer data)
Definition gui_main.c:242
resolution_request_get
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2633
set_unit_icon
void set_unit_icon(int idx, struct unit *punit)
Definition gui_main.c:2118
unit_ids
static int unit_ids[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:175
timeout_label
GtkWidget * timeout_label
Definition gui_main.c:148
gui_up
static bool gui_up
Definition gui_main.c:186
srv_id
static guint srv_id
Definition gui_main.c:183
mouse_scroll_mapcanvas
static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev)
Definition gui_main.c:706
city_productions_style
PangoFontDescription * city_productions_style
Definition gui_main.c:134
overview_scrolled_window
GtkWidget * overview_scrolled_window
Definition gui_main.c:112
detached_widget_fill
static GtkWidget * detached_widget_fill(GtkWidget *tearbox)
Definition gui_main.c:868
top_notebook
GtkWidget * top_notebook
Definition gui_main.c:129
MIGRATE_STR_OPTION
#define MIGRATE_STR_OPTION(opt)
unit_info_box
GtkWidget * unit_info_box
Definition gui_main.c:152
fc_lost_focus
gboolean fc_lost_focus(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:758
ui_exit
void ui_exit(void)
Definition gui_main.c:2088
get_gui_type
enum gui_type get_gui_type(void)
Definition gui_main.c:2099
detached_widget_new
static GtkWidget * detached_widget_new(void)
Definition gui_main.c:857
cur_y
gint cur_y
Definition gui_main.c:184
main
int main(int argc, char **argv)
Definition gui_main.c:1787
fullscreen_opt_refresh
void fullscreen_opt_refresh(struct option *poption)
Definition gui_main.c:2455
ui_init
void ui_init(void)
Definition gui_main.c:1777
free_unit_table
static void free_unit_table(void)
Definition gui_main.c:1017
idle_callback_wrapper
static gboolean idle_callback_wrapper(gpointer data)
Definition gui_main.c:2412
apply_city_names_font
static void apply_city_names_font(struct option *poption)
Definition gui_main.c:2467
apply_city_productions_font
static void apply_city_productions_font(struct option *poption)
Definition gui_main.c:2478
fc_gained_focus
gboolean fc_gained_focus(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:768
government_label
GtkWidget * government_label
Definition gui_main.c:147
sun_label
GtkWidget * sun_label
Definition gui_main.c:145
city_names_style
PangoFontDescription * city_names_style
Definition gui_main.c:133
refresh_chat_buttons
void refresh_chat_buttons(void)
Definition gui_main.c:2531
map_canvas_focus
gboolean map_canvas_focus(void)
Definition gui_main.c:382
turn_done_button
GtkWidget * turn_done_button
Definition gui_main.c:149
bottom_hpaned
static GtkWidget * bottom_hpaned
Definition gui_main.c:131
timer_id
static gint timer_id
Definition gui_main.c:181
screen_width
int screen_width(void)
Definition gui_main.c:2597
scroll_panel
GtkWidget * scroll_panel
Definition gui_main.c:141
end_turn_callback
static void end_turn_callback(GtkWidget *w, gpointer data)
Definition gui_main.c:2270
OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK
#define OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK
Definition gui_main.c:117
log_callback_utf8
static void log_callback_utf8(enum log_level level, const char *message, bool file_too)
Definition gui_main.c:230
add_idle_callback
void add_idle_callback(void(callback)(void *), void *data)
Definition gui_main.c:2427
show_info_popup
static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition gui_main.c:2239
set_g_log_callbacks
static void set_g_log_callbacks(void)
Definition gui_main.c:1761
reset_unit_table
void reset_unit_table(void)
Definition gui_main.c:1045
key_press_map_canvas
static gboolean key_press_map_canvas(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:423
unit_info_frame
GtkWidget * unit_info_frame
Definition gui_main.c:153
options_extra_init
void options_extra_init(void)
Definition gui_main.c:2501
top_vbox
GtkWidget * top_vbox
Definition gui_main.c:128
allied_chat_only_callback
static void allied_chat_only_callback(struct option *poption)
Definition gui_main.c:2440
adjust_default_options
static void adjust_default_options(void)
Definition gui_main.c:2645
set_wait_for_writable_socket
static void set_wait_for_writable_socket(struct connection *pc, bool socket_writable)
Definition gui_main.c:2290
ahbox
GtkWidget * ahbox
Definition gui_main.c:140
apply_reqtree_text_font
static void apply_reqtree_text_font(struct option *poption)
Definition gui_main.c:2489
is_gui_up
bool is_gui_up(void)
Definition gui_main.c:2080
toplevel_focus
static gboolean toplevel_focus(GtkWidget *w, GtkDirectionType arg)
Definition gui_main.c:338
reqtree_text_style
PangoFontDescription * reqtree_text_style
Definition gui_main.c:135
flake_label
GtkWidget * flake_label
Definition gui_main.c:146
g_log_to_freelog_cb
static void g_log_to_freelog_cb(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
Definition gui_main.c:1705
avbox
GtkWidget * avbox
Definition gui_main.c:140
cur_x
gint cur_x
Definition gui_main.c:184
insert_client_build_info
void insert_client_build_info(char *outbuf, size_t outlen)
Definition gui_main.c:2561
set_g_log_callback_domain
static void set_g_log_callback_domain(const char *domain)
Definition gui_main.c:1749
bulb_label
GtkWidget * bulb_label
Definition gui_main.c:144
overview_canvas
GtkWidget * overview_canvas
Definition gui_main.c:111
toplevel
GtkWidget * toplevel
Definition gui_main.c:125
setup_widgets
static void setup_widgets(void)
Definition gui_main.c:1149
OVERVIEW_CANVAS_STORE_WIDTH
#define OVERVIEW_CANVAS_STORE_WIDTH
Definition gui_main.c:118
remove_net_input
void remove_net_input(void)
Definition gui_main.c:2333
map_horizontal_scrollbar
GtkWidget * map_horizontal_scrollbar
Definition gui_main.c:108
map_canvas
GtkWidget * map_canvas
Definition gui_main.c:107
toplevel_key_press_handler
static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:622
sound_bell
void sound_bell(void)
Definition gui_main.c:2107
migrate_options_from_gtk2
static void migrate_options_from_gtk2(void)
Definition gui_main.c:1795
econ_label
GtkWidget * econ_label[10]
Definition gui_main.c:143
popup_quit_dialog
void popup_quit_dialog(void)
Definition gui_main.c:2371
migrate_options_from_gtk3
static void migrate_options_from_gtk3(void)
Definition gui_main.c:1850
gui_character_encoding
const char *const gui_character_encoding
Definition gui_main.c:161
unit_id_top
static int unit_id_top
Definition gui_main.c:174
get_net_input
static gboolean get_net_input(GIOChannel *source, GIOCondition condition, gpointer data)
Definition gui_main.c:2279
audio_paused
static bool audio_paused
Definition gui_main.c:188
map_widget
GtkWidget * map_widget
Definition gui_main.c:130
client_focus
static bool client_focus
Definition gui_main.c:189
right_notebook
GtkWidget * right_notebook
Definition gui_main.c:129
quit_gtk_main
void quit_gtk_main(void)
Definition gui_main.c:2359
allied_chat_button_toggled
static void allied_chat_button_toggled(GtkToggleButton *button, gpointer user_data)
Definition gui_main.c:2552
vmode
static struct video_mode vmode
Definition gui_main.c:191
add_net_input
void add_net_input(int sock)
Definition gui_main.c:2315
g_log_writer_to_freelog_cb
static GLogWriterOutput g_log_writer_to_freelog_cb(GLogLevelFlags log_level, const GLogField *fields, gsize n_fields, gpointer user_data)
Definition gui_main.c:1733
toplevel_tabs
GtkWidget * toplevel_tabs
Definition gui_main.c:127
allied_chat_toggle_button
static GtkWidget * allied_chat_toggle_button
Definition gui_main.c:179
overview_canvas_store_width
int overview_canvas_store_width
Definition gui_main.c:122
update_turn_done_tooltip
void update_turn_done_tooltip(void)
Definition gui_main.c:1130
tearoff_callback
static void tearoff_callback(GtkWidget *b, gpointer data)
Definition gui_main.c:812
main_message_area
GtkTextView * main_message_area
Definition gui_main.c:177
overview_canvas_store_height
int overview_canvas_store_height
Definition gui_main.c:123
screen_height
int screen_height(void)
Definition gui_main.c:2615
parse_options
static bool parse_options(int argc, char **argv)
Definition gui_main.c:295
conn_box
GtkWidget * conn_box
Definition gui_main.c:140
OVERVIEW_CANVAS_STORE_HEIGHT
#define OVERVIEW_CANVAS_STORE_HEIGHT
Definition gui_main.c:120
main_frame_civ_name
GtkWidget * main_frame_civ_name
Definition gui_main.c:137
MIGRATE_OPTION
#define MIGRATE_OPTION(opt)
gui_use_transliteration
const bool gui_use_transliteration
Definition gui_main.c:162
GUI_NAME_FULL
#define GUI_NAME_FULL
Definition gui_main.h:22
GUI_NAME_SHORT
#define GUI_NAME_SHORT
Definition gui_main.h:23
GUI_GTK_OPTION
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
dlg_tab_provider_prepare
void dlg_tab_provider_prepare(void)
Definition gui_stuff.c:1155
setup_dialog
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:287
gui_update_font_full
void gui_update_font_full(const char *font_name, const char *font_value, PangoFontDescription **font_desc)
Definition gui_stuff.c:1073
happiness_dialog_init
void happiness_dialog_init(void)
Definition happiness.c:86
happiness_dialog_done
void happiness_dialog_done(void)
Definition happiness.c:94
help_system_init
void help_system_init(void)
Definition helpdlg.c:157
intel_dialog_done
void intel_dialog_done(void)
Definition inteldlg.c:128
intel_dialog_init
void intel_dialog_init(void)
Definition inteldlg.c:119
luaconsole_dialog_init
void luaconsole_dialog_init(void)
Definition luaconsole.c:83
luaconsole_dialog_done
void luaconsole_dialog_done(void)
Definition luaconsole.c:101
move_overviewcanvas
gboolean move_overviewcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:463
move_mapcanvas
gboolean move_mapcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:406
leave_mapcanvas
gboolean leave_mapcanvas(GtkWidget *widget, GdkEventCrossing *event)
Definition mapctrl.c:435
update_city_descriptions
void update_city_descriptions(void)
Definition mapview.c:488
map_canvas_draw
gboolean map_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data)
Definition mapview.c:424
overview_canvas_draw
gboolean overview_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data)
Definition mapview.c:356
meswin_dialog_popup
void meswin_dialog_popup(bool raise)
Definition messagewin.c:417
create_start_page
GtkWidget * create_start_page(void)
Definition pages.c:2607
create_network_page
GtkWidget * create_network_page(void)
Definition pages.c:1185
create_scenario_page
GtkWidget * create_scenario_page(void)
Definition pages.c:3169
statusbar
static GtkWidget * statusbar
Definition pages.c:89
get_current_client_page
enum client_pages get_current_client_page(void)
Definition pages.c:3329
destroy_server_scans
void destroy_server_scans(void)
Definition pages.c:752
create_load_page
GtkWidget * create_load_page(void)
Definition pages.c:2888
create_statusbar
GtkWidget * create_statusbar(void)
Definition pages.c:893
create_main_page
GtkWidget * create_main_page(void)
Definition pages.c:229
science_report_dialog_redraw
void science_report_dialog_redraw(void)
Definition repodlgs.c:761
spaceship_dialog_init
void spaceship_dialog_init(void)
Definition spaceshipdlg.c:87
spaceship_dialog_done
void spaceship_dialog_done(void)
Definition spaceshipdlg.c:95
sprite_get_pixbuf
GdkPixbuf * sprite_get_pixbuf(struct sprite *sprite)
Definition sprite.c:402
ingame_votebar
GtkWidget * ingame_votebar
Definition voteinfo_bar.c:50
voteinfo_bar_new
GtkWidget * voteinfo_bar_new(bool split_bar)
Definition voteinfo_bar.c:92
reverse_taxrates_callback
gboolean reverse_taxrates_callback(GtkGestureClick *gesture, int n_press, double x, double y)
Definition dialogs.c:1459
empty_unit_paintable
static GdkPaintable * empty_unit_paintable
Definition gui_main.c:159
tearoff_close
static void tearoff_close(GtkWidget *w, gpointer data)
Definition gui_main.c:790
tearoff_reattach
static void tearoff_reattach(GtkWidget *box)
Definition gui_main.c:773
terminate_signal_processing
gboolean terminate_signal_processing(GtkEventControllerFocus *controller, gpointer data)
Definition gui_main.c:1050
more_arrow_container
static GtkWidget * more_arrow_container
Definition gui_main.c:164
unit_pic
static GtkWidget * unit_pic
Definition gui_main.c:161
select_more_arrow_callback
static gboolean select_more_arrow_callback(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition gui_main.c:2224
econ_widget
GtkWidget * econ_widget
Definition gui_main.c:154
fc_app
static GtkApplication * fc_app
Definition gui_main.c:183
gui_app
GtkApplication * gui_app(void)
Definition gui_main.c:2681
more_arrow
static GtkWidget * more_arrow
Definition gui_main.c:163
zoom_steps_custom
static float zoom_steps_custom[]
Definition gui_main.c:227
migrate_options_from_gtk3_22
static void migrate_options_from_gtk3_22(void)
Definition gui_main.c:1855
animation_idle_cb
void animation_idle_cb(void *data)
Definition gui_main.c:2436
activate_gui
static void activate_gui(GtkApplication *app, gpointer data)
Definition gui_main.c:1957
populate_unit_pic_table
static void populate_unit_pic_table(void)
Definition gui_main.c:889
info_popup_closed
static void info_popup_closed(GtkWidget *self, gpointer data)
Definition gui_main.c:2239
move_from_container_to_container
static void move_from_container_to_container(GtkWidget *wdg, GtkWidget *old_wdg, GtkWidget *new_wdg)
Definition gui_main.c:718
select_unit_pic_callback
static gboolean select_unit_pic_callback(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition gui_main.c:2192
unit_pic_table
static GtkWidget * unit_pic_table
Definition gui_main.c:160
unit_below_pic
static GtkWidget * unit_below_pic[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:162
main_message_area_resize
void main_message_area_resize(void *data)
Definition gui_main.c:368
widget_destroyed
void widget_destroyed(GtkWidget *wdg, void *data)
Definition gui_stuff.c:1155
right_butt_down_overviewcanvas
gboolean right_butt_down_overviewcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:499
left_butt_up_mapcanvas
gboolean left_butt_up_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:164
right_butt_up_mapcanvas
gboolean right_butt_up_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:181
left_butt_down_overviewcanvas
gboolean left_butt_down_overviewcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:474
left_butt_down_mapcanvas
gboolean left_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:206
right_butt_down_mapcanvas
gboolean right_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:261
middle_butt_down_mapcanvas
gboolean middle_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:330
map_canvas_resize
void map_canvas_resize(GtkWidget *w, int width, int height, gpointer data)
Definition mapview.c:408
put_unit_picture
void put_unit_picture(struct unit *punit, GtkPicture *p, int height)
Definition mapview.c:494
menus_set_initial_toggle_values
void menus_set_initial_toggle_values(void)
Definition menu.c:2941
picture_new_from_surface
GtkWidget * picture_new_from_surface(cairo_surface_t *surf)
Definition sprite.c:526
citizensinfo.h
editgui.h
gui_stuff.h
happiness.h
cma_fe.h
chatline.h
colors.h
connectdlg.h
dialogs.h
diplodlg.h
gotodlg.h
graphics.h
gui_main.h
helpdlg.h
inteldlg.h
luaconsole.h
mapctrl.h
mapview.h
menu.h
messagewin.h
optiondlg.h
pages.h
plrdlg.h
repodlgs.h
spaceshipdlg.h
voteinfo_bar.h
log_set_callback
log_callback_fn log_set_callback(log_callback_fn callback)
Definition log.c:290
log.h
fc_assert_ret
#define fc_assert_ret(condition)
Definition log.h:191
log_verbose
#define log_verbose(message,...)
Definition log.h:109
fc_assert
#define fc_assert(condition)
Definition log.h:176
log_fatal
#define log_fatal(message,...)
Definition log.h:100
log_debug
#define log_debug(message,...)
Definition log.h:115
log_normal
#define log_normal(message,...)
Definition log.h:107
log_base
#define log_base(level, message,...)
Definition log.h:94
log_level
log_level
Definition log.h:28
LOG_ERROR
@ LOG_ERROR
Definition log.h:30
LOG_DEBUG
@ LOG_DEBUG
Definition log.h:34
LOG_FATAL
@ LOG_FATAL
Definition log.h:29
LOG_WARN
@ LOG_WARN
Definition log.h:31
log_error
#define log_error(message,...)
Definition log.h:103
map.h
update_line
void update_line(int canvas_x, int canvas_y)
Definition mapctrl_common.c:665
maybe_activate_keyboardless_goto
void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
Definition mapctrl_common.c:507
rbutton_down
bool rbutton_down
Definition mapctrl_common.c:55
tiles_hilited_cities
bool tiles_hilited_cities
Definition mapctrl_common.c:60
scroll_mapview
void scroll_mapview(enum direction8 gui_dir)
Definition mapctrl_common.c:552
keyboardless_goto_button_down
bool keyboardless_goto_button_down
Definition mapctrl_common.c:69
update_selection_rectangle
void update_selection_rectangle(float canvas_x, float canvas_y)
Definition mapctrl_common.c:201
init_mapcanvas_and_overview
void init_mapcanvas_and_overview(void)
Definition mapview_common.c:3654
canvas_pos_to_tile
struct tile * canvas_pos_to_tile(float canvas_x, float canvas_y, float zoom)
Definition mapview_common.c:763
free_mapcanvas_and_overview
void free_mapcanvas_and_overview(void)
Definition mapview_common.c:3663
get_mapview_scroll_pos
void get_mapview_scroll_pos(int *scroll_x, int *scroll_y)
Definition mapview_common.c:1206
get_mapview_scroll_step
void get_mapview_scroll_step(int *xstep, int *ystep)
Definition mapview_common.c:1192
set_mapview_scroll_pos
void set_mapview_scroll_pos(int scroll_x, int scroll_y, float zoom)
Definition mapview_common.c:1215
center_tile_mapcanvas
void center_tile_mapcanvas(const struct tile *ptile)
Definition mapview_common.c:1237
update_animation
void update_animation(void)
Definition mapview_common.c:439
set_frame_by_frame_animation
void set_frame_by_frame_animation(void)
Definition mapview_common.c:4062
link_marks_clear_all
void link_marks_clear_all(void)
Definition mapview_common.c:3933
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
option_changed
void option_changed(struct option *poption)
Definition options.c:783
server_optset
const struct option_set * server_optset
Definition options.c:4281
client_optset
const struct option_set * client_optset
Definition options.c:1315
option_bool_get
bool option_bool_get(const struct option *poption)
Definition options.c:832
option_type
enum option_type option_type(const struct option *poption)
Definition options.c:693
option_font_target
const char * option_font_target(const struct option *poption)
Definition options.c:1198
string_to_video_mode
bool string_to_video_mode(const char *buf, struct video_mode *mode)
Definition options.c:6761
gui_options
struct client_options gui_options
Definition options.c:71
option_font_get
const char * option_font_get(const struct option *poption)
Definition options.c:1176
optset_option_by_name
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:466
options.h
GUI_GTK_OVERVIEW_MIN_XSIZE
#define GUI_GTK_OVERVIEW_MIN_XSIZE
Definition options.h:635
options_iterate
#define options_iterate(poptset, poption)
Definition options.h:588
GUI_GTK_MSGCHAT_MERGED
@ GUI_GTK_MSGCHAT_MERGED
Definition options.h:69
GUI_GTK_MSGCHAT_SPLIT
@ GUI_GTK_MSGCHAT_SPLIT
Definition options.h:67
options_iterate_end
#define options_iterate_end
Definition options.h:593
get_info_label_text_popup
const char * get_info_label_text_popup(void)
Definition text.c:982
level
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:190
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
y
struct sprite int int y
Definition sprite_g.h:31
x
struct sprite int x
Definition sprite_g.h:31
callback
Definition gui_main.c:2404
callback::data
void * data
Definition gui_main.c:2406
callback::callback
void(* callback)(void *data)
Definition gui_main.c:2405
civclient::conn
struct connection conn
Definition client_main.h:96
client_options::silent_when_not_in_focus
bool silent_when_not_in_focus
Definition options.h:192
client_options::gui_gtk3_22_migrated_from_gtk3
bool gui_gtk3_22_migrated_from_gtk3
Definition options.h:134
client_options::gui_gtk3_migrated_from_2_5
bool gui_gtk3_migrated_from_2_5
Definition options.h:140
client_options::zoom_set
bool zoom_set
Definition options.h:231
client_options::sound_effects_volume
int sound_effects_volume
Definition options.h:191
client_options::first_boot
bool first_boot
Definition options.h:128
client_options::zoom_default_level
float zoom_default_level
Definition options.h:232
client_options::gui_gtk3_fullscreen
bool gui_gtk3_fullscreen
Definition options.h:267
client_options::migrate_fullscreen
bool migrate_fullscreen
Definition options.h:146
client_options::gui_gtk3_migrated_from_gtk2
bool gui_gtk3_migrated_from_gtk2
Definition options.h:133
color
Definition colors.h:21
connection
Definition connection.h:136
connection::notify_of_writable_data
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition connection.h:181
connection::used
bool used
Definition connection.h:139
editbar::widget
GtkWidget * widget
Definition editgui.h:26
message
Definition messagewin_common.h:29
option
Definition options.c:514
sprite
Definition sprite.h:22
tileset
Definition tilespec.c:481
unit
Definition unit.h:140
unit::id
int id
Definition unit.h:147
video_mode
Definition options.h:46
video_mode::height
int height
Definition options.h:48
video_mode::width
int width
Definition options.h:47
view
Definition mapview_common.h:36
widget
Definition widget.h:112
fc_snprintf
int fc_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:960
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:986
support.h
TRUE
#define TRUE
Definition support.h:46
FALSE
#define FALSE
Definition support.h:47
text.h
tileset_load_tiles
void tileset_load_tiles(struct tileset *t)
Definition tilespec.c:3641
tileset_free_tiles
void tileset_free_tiles(struct tileset *t)
Definition tilespec.c:6622
tileset_use_preferred_theme
void tileset_use_preferred_theme(const struct tileset *t)
Definition tilespec.c:7087
tileset_init
void tileset_init(struct tileset *t)
Definition tilespec.c:7148
get_arrow_sprite
struct sprite * get_arrow_sprite(const struct tileset *t, enum arrow_type arrow)
Definition tilespec.c:6886
get_tax_sprite
struct sprite * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Definition tilespec.c:6897
tileset_tile_width
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:753
tilespec.h
ARROW_RIGHT
@ ARROW_RIGHT
Definition tilespec.h:202
unit_tile
#define unit_tile(_pu)
Definition unit.h:397
unit_owner
#define unit_owner(_pu)
Definition unit.h:396
unitlist.h
version.h
mouse_zoom
float mouse_zoom
Definition zoom.c:28
zoom_phase_set
void zoom_phase_set(bool individual_tiles)
Definition zoom.c:97
zoom_set_steps
void zoom_set_steps(float *steps)
Definition zoom.c:84
zoom_step_down
void zoom_step_down(void)
Definition zoom.c:134
zoom_step_up
void zoom_step_up(void)
Definition zoom.c:110
zoom.h