Freeciv-3.1: /fast/freeciv/nightly/S3_1/client/gui-gtk-3.0/gui_main.c Source File

Freeciv-3.1

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 "client_main.h"
65#include "climisc.h"
66#include "clinet.h"
67#include "colors.h"
68#include "connectdlg_common.h"
69#include "control.h"
70#include "editor.h"
71#include "options.h"
72#include "text.h"
73#include "tilespec.h"
74#include "zoom.h"
75
76/* client/gui-gtk-3.0 */
77#include "chatline.h"
78#include "citizensinfo.h"
79#include "connectdlg.h"
80#include "cma_fe.h"
81#include "dialogs.h"
82#include "diplodlg.h"
83#include "editgui.h"
84#include "gotodlg.h"
85#include "graphics.h"
86#include "gui_stuff.h"
87#include "happiness.h"
88#include "helpdlg.h"
89#include "inteldlg.h"
90#include "mapctrl.h"
91#include "mapview.h"
92#include "menu.h"
93#include "messagewin.h"
94#include "optiondlg.h"
95#include "pages.h"
96#include "plrdlg.h"
97#include "luaconsole.h"
98#include "spaceshipdlg.h"
99#include "repodlgs.h"
100#include "voteinfo_bar.h"
101
102#include "gui_main.h"
103
104 const char *client_string = GUI_NAME_FULL;
105
106GtkWidget *map_canvas; /* GtkDrawingArea */
107GtkWidget *map_horizontal_scrollbar;
108GtkWidget *map_vertical_scrollbar;
109
110GtkWidget *overview_canvas; /* GtkDrawingArea */
111GtkWidget *overview_scrolled_window; /* GtkScrolledWindow */
112/* The two values below define the width and height of the map overview. The
113 * first set of values (2*62, 2*46) define the size for a netbook display. For
114 * bigger displays the values are doubled (default). */
115#define OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK (2 * 64)
116#define OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK (2 * 46)
117#define OVERVIEW_CANVAS_STORE_WIDTH \
118 (2 * OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK)
119#define OVERVIEW_CANVAS_STORE_HEIGHT \
120 (2 * OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK)
121 int overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH;
122 int overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT;
123
124GtkWidget *toplevel;
125GdkWindow *root_window;
126GtkWidget *toplevel_tabs;
127GtkWidget *top_vbox;
128GtkWidget *top_notebook, *bottom_notebook, *right_notebook;
129GtkWidget *map_widget;
130 static GtkWidget *bottom_hpaned;
131
132PangoFontDescription *city_names_style = NULL;
133PangoFontDescription *city_productions_style = NULL;
134PangoFontDescription *reqtree_text_style = NULL;
135
136GtkWidget *main_frame_civ_name;
137GtkWidget *main_label_info;
138
139GtkWidget *avbox, *ahbox, *conn_box;
140GtkWidget* scroll_panel;
141
142GtkWidget *econ_label[10];
143GtkWidget *bulb_label;
144GtkWidget *sun_label;
145GtkWidget *flake_label;
146GtkWidget *government_label;
147GtkWidget *timeout_label;
148GtkWidget *turn_done_button;
149
150GtkWidget *unit_info_label;
151GtkWidget *unit_info_box;
152GtkWidget *unit_info_frame;
153
154GtkWidget *econ_ebox;
155GtkWidget *bulb_ebox;
156GtkWidget *sun_ebox;
157GtkWidget *flake_ebox;
158GtkWidget *government_ebox;
159
160 const char *const gui_character_encoding = "UTF-8";
161 const bool gui_use_transliteration = FALSE;
162
163 static GtkWidget *main_menubar;
164 static GtkWidget *unit_image_table;
165 static GtkWidget *unit_image;
166 static GtkWidget *unit_image_button;
167 static GtkWidget *unit_below_image[MAX_NUM_UNITS_BELOW];
168 static GtkWidget *unit_below_image_button[MAX_NUM_UNITS_BELOW];
169 static GtkWidget *more_arrow_pixmap;
170 static GtkWidget *more_arrow_pixmap_button;
171 static GtkWidget *more_arrow_pixmap_container;
172
173 static int unit_id_top;
174 static int unit_ids[MAX_NUM_UNITS_BELOW]; /* ids of the units icons in
175 * information display: (or 0) */
176GtkTextView *main_message_area;
177GtkTextBuffer *message_buffer = NULL;
178 static GtkWidget *allied_chat_toggle_button;
179
180 static gint timer_id; /* ditto */
181 static GIOChannel *srv_channel;
182 static guint srv_id;
183gint cur_x, cur_y;
184
185 static bool gui_up = FALSE;
186
187 static struct video_mode vmode = { -1, -1 };
188
189static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data);
190static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, 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 bool parse_options(int argc, char **argv);
200static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev, gpointer data);
201static gboolean toplevel_key_release_handler(GtkWidget *w, GdkEventKey *ev, gpointer data);
202static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev);
203
204static void tearoff_callback(GtkWidget *b, gpointer data);
205static GtkWidget *detached_widget_new(void);
206static GtkWidget *detached_widget_fill(GtkWidget *tearbox);
207
208static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev,
209 gpointer data);
210static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev,
211 gpointer data);
212static gboolean quit_dialog_callback(void);
213
214static void allied_chat_button_toggled(GtkToggleButton *button,
215 gpointer user_data);
216
217static void free_unit_table(void);
218
219static void adjust_default_options(void);
220
221/**********************************************************************/
224 static void log_callback_utf8(enum log_level level, const char *message,
225 bool file_too)
226{
227 if (!file_too || level <= LOG_FATAL) {
228 fc_fprintf(stderr, "%d: %s\n", level, message);
229 }
230}
231
232/**********************************************************************/
236 static gboolean timer_callback(gpointer data)
237{
238 double seconds = real_timer_callback();
239
240 timer_id = g_timeout_add(seconds * 1000, timer_callback, NULL);
241
242 return FALSE;
243}
244
245/**********************************************************************/
249 static void print_usage(void)
250{
251 /* add client-specific usage information here */
252 fc_fprintf(stderr,
253 _("This client accepts the standard Gtk command-line options\n"
254 "after '--'. See the Gtk documentation.\n\n"));
255
256 fc_fprintf(stderr,
257 _("Other gui-specific options are:\n"));
258
259 fc_fprintf(stderr,
260 _("-g, --gtk-warnings\tAllow Gtk+ to print warnings "
261 "to console\n"));
262
263 fc_fprintf(stderr,
264 _("-r, --resolution WIDTHxHEIGHT\tAssume given resolution "
265 "screen\n"));
266
267 fc_fprintf(stderr, "\n");
268
269 /* TRANS: No full stop after the URL, could cause confusion. */
270 fc_fprintf(stderr, _("Report bugs at %s\n"), BUG_URL);
271}
272
273/**********************************************************************/
276 static void log_gtk_warns(const gchar *log_domain, GLogLevelFlags log_level,
277 const gchar *message,
278 gpointer user_data)
279{
280 log_verbose("%s", message);
281}
282
283/**********************************************************************/
286 static bool parse_options(int argc, char **argv)
287{
288 int i = 1;
289 bool gtk_warns_enabled = FALSE;
290
291 while (i < argc) {
292 char *option = NULL;
293
294 if (is_option("--help", argv[i])) {
295 print_usage();
296
297 return FALSE;
298 } else if (is_option("--gtk-warnings", argv[i])) {
299 gtk_warns_enabled = TRUE;
300 } else if ((option = get_option_malloc("--resolution", argv, &i, argc, FALSE))) {
301 if (!string_to_video_mode(option, &vmode)) {
302 fc_fprintf(stderr, _("Illegal video mode '%s'\n"), option);
303 exit(EXIT_FAILURE);
304 }
305 free(option);
306 }
307 /* Can't check against unknown options, as those might be gtk options */
308
309 i++;
310 }
311
312 if (!gtk_warns_enabled) {
313 g_log_set_handler("Gtk", G_LOG_LEVEL_WARNING, log_gtk_warns, NULL);
314 }
315
316 return TRUE;
317}
318
319/**********************************************************************/
322 static gboolean toplevel_focus(GtkWidget *w, GtkDirectionType arg)
323{
324 switch (arg) {
325 case GTK_DIR_TAB_FORWARD:
326 case GTK_DIR_TAB_BACKWARD:
327
328 if (!gtk_widget_get_can_focus(w)) {
329 return FALSE;
330 }
331
332 if (!gtk_widget_is_focus(w)) {
333 gtk_widget_grab_focus(w);
334 return TRUE;
335 }
336 break;
337
338 default:
339 break;
340 }
341 return FALSE;
342}
343
344/**********************************************************************/
349 static void main_message_area_size_allocate(GtkWidget *widget,
350 GtkAllocation *allocation,
351 gpointer data)
352{
353 static int old_width = 0, old_height = 0;
354
355 if (allocation->width != old_width
356 || allocation->height != old_height) {
357 chatline_scroll_to_bottom(TRUE);
358 old_width = allocation->width;
359 old_height = allocation->height;
360 }
361}
362
363/**********************************************************************/
366gboolean map_canvas_focus(void)
367{
368 gtk_window_present(GTK_WINDOW(toplevel));
369 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 0);
370 gtk_widget_grab_focus(map_canvas);
371 return TRUE;
372}
373
374/**********************************************************************/
383 static gboolean toplevel_handler(GtkWidget *w, GdkEvent *ev, gpointer data)
384{
385 GtkWidget *focus;
386
387 focus = gtk_window_get_focus(GTK_WINDOW(toplevel));
388 if (focus) {
389 if (GTK_IS_ENTRY(focus)
390 || (GTK_IS_TEXT_VIEW(focus)
391 && gtk_text_view_get_editable(GTK_TEXT_VIEW(focus)))) {
392 /* Propagate event to currently focused entry widget. */
393 if (gtk_widget_event(focus, ev)) {
394 /* Do not propagate event to our children. */
395 return TRUE;
396 }
397 }
398 }
399
400 /* Continue propagating event to our children. */
401 return FALSE;
402}
403
404/**********************************************************************/
407 static gboolean key_press_map_canvas(GtkWidget *w, GdkEventKey *ev,
408 gpointer data)
409{
410 if ((ev->state & GDK_SHIFT_MASK)) {
411 switch (ev->keyval) {
412
413 case GDK_KEY_Left:
414 scroll_mapview(DIR8_WEST);
415 return TRUE;
416
417 case GDK_KEY_Right:
418 scroll_mapview(DIR8_EAST);
419 return TRUE;
420
421 case GDK_KEY_Up:
422 scroll_mapview(DIR8_NORTH);
423 return TRUE;
424
425 case GDK_KEY_Down:
426 scroll_mapview(DIR8_SOUTH);
427 return TRUE;
428
429 case GDK_KEY_Home:
430 key_center_capital();
431 return TRUE;
432
433 case GDK_KEY_Page_Up:
434 g_signal_emit_by_name(main_message_area, "move_cursor",
435 GTK_MOVEMENT_PAGES, -1, FALSE);
436 return TRUE;
437
438 case GDK_KEY_Page_Down:
439 g_signal_emit_by_name(main_message_area, "move_cursor",
440 GTK_MOVEMENT_PAGES, 1, FALSE);
441 return TRUE;
442
443 default:
444 break;
445 }
446 } else if (!(ev->state & GDK_CONTROL_MASK)) {
447 switch (ev->keyval) {
448 default:
449 break;
450 }
451 }
452
453 if (ev->state & GDK_SHIFT_MASK) {
454 bool volchange = FALSE;
455
456 switch (ev->keyval) {
457 case GDK_KEY_plus:
458 case GDK_KEY_KP_Add:
459 gui_options.sound_effects_volume += 10;
460 volchange = TRUE;
461 break;
462
463 case GDK_KEY_minus:
464 case GDK_KEY_KP_Subtract:
465 gui_options.sound_effects_volume -= 10;
466 volchange = TRUE;
467 break;
468
469 default:
470 break;
471 }
472
473 if (volchange) {
474 struct option *poption = optset_option_by_name(client_optset, "sound_effects_volume");
475
476 gui_options.sound_effects_volume = CLIP(0, gui_options.sound_effects_volume, 100);
477 option_changed(poption);
478
479 return TRUE;
480 }
481 } else if (!(ev->state & GDK_CONTROL_MASK)) {
482 switch (ev->keyval) {
483 case GDK_KEY_plus:
484 case GDK_KEY_KP_Add:
485 zoom_step_up();
486 return TRUE;
487
488 case GDK_KEY_minus:
489 case GDK_KEY_KP_Subtract:
490 zoom_step_down();
491 return TRUE;
492
493 default:
494 break;
495 }
496 }
497
498 /* Return here if observer */
499 if (client_is_observer()) {
500 return FALSE;
501 }
502
503 switch (ev->keyval) {
504
505 case GDK_KEY_KP_Up:
506 case GDK_KEY_KP_8:
507 case GDK_KEY_Up:
508 case GDK_KEY_8:
509 key_unit_move(DIR8_NORTH);
510 return TRUE;
511
512 case GDK_KEY_KP_Page_Up:
513 case GDK_KEY_KP_9:
514 case GDK_KEY_Page_Up:
515 case GDK_KEY_9:
516 key_unit_move(DIR8_NORTHEAST);
517 return TRUE;
518
519 case GDK_KEY_KP_Right:
520 case GDK_KEY_KP_6:
521 case GDK_KEY_Right:
522 case GDK_KEY_6:
523 key_unit_move(DIR8_EAST);
524 return TRUE;
525
526 case GDK_KEY_KP_Page_Down:
527 case GDK_KEY_KP_3:
528 case GDK_KEY_Page_Down:
529 case GDK_KEY_3:
530 key_unit_move(DIR8_SOUTHEAST);
531 return TRUE;
532
533 case GDK_KEY_KP_Down:
534 case GDK_KEY_KP_2:
535 case GDK_KEY_Down:
536 case GDK_KEY_2:
537 key_unit_move(DIR8_SOUTH);
538 return TRUE;
539
540 case GDK_KEY_KP_End:
541 case GDK_KEY_KP_1:
542 case GDK_KEY_End:
543 case GDK_KEY_1:
544 key_unit_move(DIR8_SOUTHWEST);
545 return TRUE;
546
547 case GDK_KEY_KP_Left:
548 case GDK_KEY_KP_4:
549 case GDK_KEY_Left:
550 case GDK_KEY_4:
551 key_unit_move(DIR8_WEST);
552 return TRUE;
553
554 case GDK_KEY_KP_Home:
555 case GDK_KEY_KP_7:
556 case GDK_KEY_Home:
557 case GDK_KEY_7:
558 key_unit_move(DIR8_NORTHWEST);
559 return TRUE;
560
561 case GDK_KEY_KP_Begin:
562 case GDK_KEY_KP_5:
563 case GDK_KEY_5:
564 key_recall_previous_focus_unit();
565 return TRUE;
566
567 case GDK_KEY_Escape:
568 key_cancel_action();
569 return TRUE;
570
571 case GDK_KEY_b:
572 if (tiles_hilited_cities) {
573 buy_production_in_selected_cities();
574 return TRUE;
575 }
576 break;
577
578 default:
579 break;
580 };
581
582 return FALSE;
583}
584
585/**********************************************************************/
588 static gboolean toplevel_key_release_handler(GtkWidget *w, GdkEventKey *ev,
589 gpointer data)
590{
591 /* inputline history code */
592 if (!gtk_widget_get_mapped(top_vbox) || inputline_has_focus()) {
593 return FALSE;
594 }
595
596 if (editor_is_active()) {
597 return handle_edit_key_release(ev);
598 }
599
600 return FALSE;
601}
602
603/**********************************************************************/
606 static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev,
607 gpointer data)
608{
609 if (inputline_has_focus()) {
610 return FALSE;
611 }
612
613 if (ev->keyval == GDK_KEY_apostrophe) {
614 /* Allow this even if not in main map view; chatline is present on
615 * some other pages too */
616
617 /* Make the chatline visible if it's not currently.
618 * FIXME: should find the correct window, even when detached, from any
619 * other window; should scroll to the bottom automatically showing the
620 * latest text from other players; MUST NOT make spurious text windows
621 * at the bottom of other dialogs. */
622 if (gtk_widget_get_mapped(top_vbox)) {
623 /* The main game view is visible. May need to switch notebook. */
624 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
625 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 1);
626 } else {
627 gtk_notebook_set_current_page(GTK_NOTEBOOK(bottom_notebook), 0);
628 }
629 }
630
631 /* If the chatline is (now) visible, focus it. */
632 if (inputline_is_visible()) {
633 inputline_grab_focus();
634 return TRUE;
635 }
636 }
637
638 if (!gtk_widget_get_mapped(top_vbox)
639 || !can_client_change_view()) {
640 return FALSE;
641 }
642
643 if (editor_is_active()) {
644 if (handle_edit_key_press(ev)) {
645 return TRUE;
646 }
647 }
648
649 if (ev->state & GDK_SHIFT_MASK) {
650 switch (ev->keyval) {
651
652 case GDK_KEY_Return:
653 case GDK_KEY_KP_Enter:
654 key_end_turn();
655 return TRUE;
656
657 default:
658 break;
659 }
660 }
661
662 if (0 == gtk_notebook_get_current_page(GTK_NOTEBOOK(top_notebook))) {
663 /* 0 means the map view is focused. */
664 return key_press_map_canvas(w, ev, data);
665 }
666
667#if 0
668 /* We are focused some other dialog, tab, or widget. */
669 if ((ev->state & GDK_CONTROL_MASK)) {
670 } else if ((ev->state & GDK_SHIFT_MASK)) {
671 } else {
672 switch (ev->keyval) {
673
674 case GDK_KEY_F4:
675 map_canvas_focus();
676 return TRUE;
677
678 default:
679 break;
680 };
681 }
682#endif /* 0 */
683
684 return FALSE;
685}
686
687/**********************************************************************/
690 static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev)
691{
692 int scroll_x, scroll_y, xstep, ystep;
693
694 if (!can_client_change_view()) {
695 return FALSE;
696 }
697
698 get_mapview_scroll_pos(&scroll_x, &scroll_y);
699 get_mapview_scroll_step(&xstep, &ystep);
700
701 switch (ev->direction) {
702 case GDK_SCROLL_UP:
703 scroll_y -= ystep*2;
704 break;
705 case GDK_SCROLL_DOWN:
706 scroll_y += ystep*2;
707 break;
708 case GDK_SCROLL_RIGHT:
709 scroll_x += xstep*2;
710 break;
711 case GDK_SCROLL_LEFT:
712 scroll_x -= xstep*2;
713 break;
714 default:
715 return FALSE;
716 };
717
718 set_mapview_scroll_pos(scroll_x, scroll_y, mouse_zoom);
719
720 /* Emulating mouse move now */
721 if (!gtk_widget_has_focus(map_canvas)) {
722 gtk_widget_grab_focus(map_canvas);
723 }
724
725 update_line(ev->x, ev->y);
726 if (rbutton_down && (ev->state & GDK_BUTTON3_MASK)) {
727 update_selection_rectangle(ev->x, ev->y);
728 }
729
730 if (keyboardless_goto_button_down && hover_state == HOVER_NONE) {
731 maybe_activate_keyboardless_goto(cur_x, cur_y);
732 }
733
734 control_mouse_cursor(canvas_pos_to_tile(cur_x, cur_y, mouse_zoom));
735
736 return TRUE;
737}
738
739/**********************************************************************/
742 static void tearoff_destroy(GtkWidget *w, gpointer data)
743{
744 GtkWidget *p, *b, *box;
745
746 box = GTK_WIDGET(data);
747 p = g_object_get_data(G_OBJECT(w), "parent");
748 b = g_object_get_data(G_OBJECT(w), "toggle");
749 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(b), FALSE);
750
751 gtk_widget_hide(w);
752 gtk_widget_reparent(box, p);
753}
754
755/**********************************************************************/
758 static gboolean propagate_keypress(GtkWidget *w, GdkEvent *ev)
759{
760 gtk_widget_event(toplevel, ev);
761
762 return FALSE;
763}
764
765/**********************************************************************/
769 static void tearoff_callback(GtkWidget *b, gpointer data)
770{
771 GtkWidget *box = GTK_WIDGET(data);
772 GtkWidget *w;
773
774 if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(b))) {
775 GtkWidget *temp_hide;
776
777 w = gtk_window_new(GTK_WINDOW_TOPLEVEL);
778 setup_dialog(w, toplevel);
779 gtk_widget_set_name(w, "Freeciv");
780 gtk_window_set_title(GTK_WINDOW(w), _("Freeciv"));
781 gtk_window_set_position(GTK_WINDOW(w), GTK_WIN_POS_MOUSE);
782 g_signal_connect(w, "destroy", G_CALLBACK(tearoff_destroy), box);
783 g_signal_connect(w, "key_press_event",
784 G_CALLBACK(propagate_keypress), NULL);
785
786 g_object_set_data(G_OBJECT(w), "parent", gtk_widget_get_parent(box));
787 g_object_set_data(G_OBJECT(w), "toggle", b);
788 temp_hide = g_object_get_data(G_OBJECT(box), "hide-over-reparent");
789 if (temp_hide != NULL) {
790 gtk_widget_hide(temp_hide);
791 }
792 gtk_widget_reparent(box, w);
793 gtk_widget_show(w);
794 if (temp_hide != NULL) {
795 gtk_widget_show(temp_hide);
796 }
797 } else {
798 gtk_widget_destroy(gtk_widget_get_parent(box));
799 }
800}
801
802/**********************************************************************/
805 static GtkWidget *detached_widget_new(void)
806{
807 GtkWidget *hgrid = gtk_grid_new();
808
809 gtk_grid_set_column_spacing(GTK_GRID(hgrid), 2);
810 return hgrid;
811}
812
813/**********************************************************************/
817 static GtkWidget *detached_widget_fill(GtkWidget *tearbox)
818{
819 GtkWidget *b, *fillbox;
820
821 b = gtk_toggle_button_new();
822 gtk_container_add(GTK_CONTAINER(tearbox), b);
823 g_signal_connect(b, "toggled", G_CALLBACK(tearoff_callback), tearbox);
824
825 fillbox = gtk_grid_new();
826 gtk_orientable_set_orientation(GTK_ORIENTABLE(fillbox),
827 GTK_ORIENTATION_VERTICAL);
828
829 gtk_container_add(GTK_CONTAINER(tearbox), fillbox);
830
831 return fillbox;
832}
833
834/**********************************************************************/
841 static void populate_unit_image_table(void)
842{
843 int i, width;
844 GtkWidget *table = unit_image_table;
845 GdkPixbuf *pix;
846 int ttw;
847
848 /* Get width of the overview window */
849 width = (overview_canvas_store_width > GUI_GTK_OVERVIEW_MIN_XSIZE)
850 ? overview_canvas_store_width
851 : GUI_GTK_OVERVIEW_MIN_XSIZE;
852
853 ttw = tileset_tile_width(tileset);
854
855 if (GUI_GTK_OPTION(small_display_layout)) {
856 /* We want arrow to appear if there is other units in addition
857 to active one in tile. Active unit is not counted, so there
858 can be 0 other units to not to display arrow. */
859 num_units_below = 1 - 1;
860 } else {
861 num_units_below = width / ttw;
862 num_units_below = CLIP(1, num_units_below, MAX_NUM_UNITS_BELOW);
863 }
864
865 /* Top row: the active unit. */
866 /* Note, we ref this and other widgets here so that we can unref them
867 * in reset_unit_table. */
868 unit_image = gtk_image_new();
869 gtk_widget_add_events(unit_image, GDK_BUTTON_PRESS_MASK);
870 g_object_ref(unit_image);
871 unit_image_button = gtk_event_box_new();
872 gtk_widget_set_size_request(unit_image_button, ttw, -1);
873 gtk_event_box_set_visible_window(GTK_EVENT_BOX(unit_image_button), FALSE);
874 g_object_ref(unit_image_button);
875 gtk_container_add(GTK_CONTAINER(unit_image_button), unit_image);
876 gtk_grid_attach(GTK_GRID(table), unit_image_button, 0, 0, 1, 1);
877 g_signal_connect(unit_image_button, "button_press_event",
878 G_CALLBACK(select_unit_image_callback),
879 GINT_TO_POINTER(-1));
880
881 if (!GUI_GTK_OPTION(small_display_layout)) {
882 /* Bottom row: other units in the same tile. */
883 for (i = 0; i < num_units_below; i++) {
884 unit_below_image[i] = gtk_image_new();
885 g_object_ref(unit_below_image[i]);
886 gtk_widget_add_events(unit_below_image[i], GDK_BUTTON_PRESS_MASK);
887 unit_below_image_button[i] = gtk_event_box_new();
888 g_object_ref(unit_below_image_button[i]);
889 gtk_widget_set_size_request(unit_below_image_button[i], ttw, -1);
890 gtk_event_box_set_visible_window(GTK_EVENT_BOX(unit_below_image_button[i]),
891 FALSE);
892 gtk_container_add(GTK_CONTAINER(unit_below_image_button[i]),
893 unit_below_image[i]);
894 g_signal_connect(unit_below_image_button[i],
895 "button_press_event",
896 G_CALLBACK(select_unit_image_callback),
897 GINT_TO_POINTER(i));
898
899 gtk_grid_attach(GTK_GRID(table), unit_below_image_button[i],
900 i, 1, 1, 1);
901 }
902 }
903
904 /* Create arrow (popup for all units on the selected tile) */
905 pix = sprite_get_pixbuf(get_arrow_sprite(tileset, ARROW_RIGHT));
906 more_arrow_pixmap = gtk_image_new_from_pixbuf(pix);
907 g_object_ref(more_arrow_pixmap);
908 more_arrow_pixmap_button = gtk_event_box_new();
909 g_object_ref(more_arrow_pixmap_button);
910 gtk_event_box_set_visible_window(GTK_EVENT_BOX(more_arrow_pixmap_button),
911 FALSE);
912 gtk_container_add(GTK_CONTAINER(more_arrow_pixmap_button),
913 more_arrow_pixmap);
914 g_signal_connect(more_arrow_pixmap_button,
915 "button_press_event",
916 G_CALLBACK(select_more_arrow_pixmap_callback), NULL);
917 /* An extra layer so that we can hide the clickable button but keep
918 * an explicit size request to avoid the layout jumping around */
919 more_arrow_pixmap_container = gtk_alignment_new(0.5, 0.5, 0, 0);
920 g_object_ref(more_arrow_pixmap_container);
921 gtk_container_add(GTK_CONTAINER(more_arrow_pixmap_container),
922 more_arrow_pixmap_button);
923 gtk_widget_set_size_request(more_arrow_pixmap_container,
924 gdk_pixbuf_get_width(pix), -1);
925 g_object_unref(G_OBJECT(pix));
926
927 if (!GUI_GTK_OPTION(small_display_layout)) {
928 /* Display on bottom row. */
929 gtk_grid_attach(GTK_GRID(table), more_arrow_pixmap_container,
930 num_units_below, 1, 1, 1);
931 } else {
932 /* Display on top row (there is no bottom row). */
933 gtk_grid_attach(GTK_GRID(table), more_arrow_pixmap_container,
934 1, 0, 1, 1);
935 }
936
937 gtk_widget_show_all(table);
938}
939
940/**********************************************************************/
943 static void free_unit_table(void)
944{
945 if (unit_image_button) {
946 gtk_container_remove(GTK_CONTAINER(unit_image_table),
947 unit_image_button);
948 g_object_unref(unit_image);
949 g_object_unref(unit_image_button);
950 if (!GUI_GTK_OPTION(small_display_layout)) {
951 int i;
952
953 for (i = 0; i < num_units_below; i++) {
954 gtk_container_remove(GTK_CONTAINER(unit_image_table),
955 unit_below_image_button[i]);
956 g_object_unref(unit_below_image[i]);
957 g_object_unref(unit_below_image_button[i]);
958 }
959 }
960 gtk_container_remove(GTK_CONTAINER(unit_image_table),
961 more_arrow_pixmap_container);
962 g_object_unref(more_arrow_pixmap);
963 g_object_unref(more_arrow_pixmap_button);
964 g_object_unref(more_arrow_pixmap_container);
965 }
966}
967
968/**********************************************************************/
971 void reset_unit_table(void)
972{
973 /* Unreference all of the widgets that we're about to reallocate, thus
974 * avoiding a memory leak. Remove them from the container first, just
975 * to be safe. Note, the widgets are ref'd in
976 * populate_unit_image_table. */
977 free_unit_table();
978
979 populate_unit_image_table();
980
981 /* We have to force a redraw of the units. And we explicitly have
982 * to force a redraw of the focus unit, which is normally only
983 * redrawn when the focus changes. We also have to force the 'more'
984 * arrow to go away, both by expicitly hiding it and telling it to
985 * do so (this will be reset immediately afterwards if necessary,
986 * but we have to make the *internal* state consistent). */
987 gtk_widget_hide(more_arrow_pixmap_button);
988 set_unit_icons_more_arrow(FALSE);
989 if (get_num_units_in_focus() == 1) {
990 set_unit_icon(-1, head_of_units_in_focus());
991 } else {
992 set_unit_icon(-1, NULL);
993 }
994 update_unit_pix_label(get_units_in_focus());
995}
996
997/**********************************************************************/
1000 void enable_menus(bool enable)
1001{
1002 if (enable) {
1003 main_menubar = setup_menus(toplevel);
1004 /* Ensure the menus are really created before performing any operations
1005 * on them. */
1006 while (gtk_events_pending()) {
1007 gtk_main_iteration();
1008 }
1009 gtk_grid_attach_next_to(GTK_GRID(top_vbox), main_menubar, NULL, GTK_POS_TOP, 1, 1);
1010 menus_init();
1011 gtk_widget_show_all(main_menubar);
1012 } else {
1013 gtk_widget_destroy(main_menubar);
1014 }
1015}
1016
1017/**********************************************************************/
1023 static gboolean right_notebook_button_release(GtkWidget *widget,
1024 GdkEventButton *event)
1025{
1026 if (event->type != GDK_BUTTON_RELEASE) {
1027 return FALSE;
1028 }
1029
1030 if (!GTK_IS_NOTEBOOK(widget)
1031 || -1 == gtk_notebook_get_current_page(GTK_NOTEBOOK(widget))) {
1032 /* Make sure the default gtk handler
1033 * does NOT get called in this case. */
1034 return TRUE;
1035 }
1036
1037 return FALSE;
1038}
1039
1040/**********************************************************************/
1043 static void setup_canvas_color_for_state(GtkStateFlags state)
1044{
1045 gtk_widget_override_background_color(GTK_WIDGET(overview_canvas), state,
1046 &get_color(tileset, COLOR_OVERVIEW_UNKNOWN)->color);
1047 gtk_widget_override_background_color(GTK_WIDGET(map_canvas), state,
1048 &get_color(tileset, COLOR_OVERVIEW_UNKNOWN)->color);
1049}
1050
1051/**********************************************************************/
1054 void update_turn_done_tooltip(void)
1055{
1056 struct option *opt = optset_option_by_name(server_optset, "fixedlength");
1057
1058 if (opt != NULL && option_bool_get(opt)) {
1059 gtk_widget_set_tooltip_text(turn_done_button,
1060 _("Fixed length turns"));
1061 } else {
1062 char buf[256];
1063
1064 fc_snprintf(buf, sizeof(buf), "%s:\n%s",
1065 _("Turn Done"), _("Shift+Return"));
1066 gtk_widget_set_tooltip_text(turn_done_button, buf);
1067 }
1068}
1069
1070/**********************************************************************/
1073 static void setup_widgets(void)
1074{
1075 GtkWidget *page, *ebox, *hgrid, *hgrid2, *label;
1076 GtkWidget *frame, *table, *table2, *paned, *sw, *text;
1077 GtkWidget *button, *view, *vgrid, *right_vbox = NULL;
1078 int i;
1079 struct sprite *spr;
1080 GtkWidget *notebook, *statusbar;
1081 GtkWidget *dtach_lowbox = NULL;
1082
1083 message_buffer = gtk_text_buffer_new(NULL);
1084
1085 notebook = gtk_notebook_new();
1086
1087 /* Stop mouse wheel notebook page switching. */
1088 g_signal_connect(notebook, "scroll_event",
1089 G_CALLBACK(gtk_true), NULL);
1090
1091 toplevel_tabs = notebook;
1092 gtk_notebook_set_show_tabs(GTK_NOTEBOOK(notebook), FALSE);
1093 gtk_notebook_set_show_border(GTK_NOTEBOOK(notebook), FALSE);
1094 vgrid = gtk_grid_new();
1095 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1096 GTK_ORIENTATION_VERTICAL);
1097 gtk_grid_set_row_spacing(GTK_GRID(vgrid), 4);
1098 gtk_container_add(GTK_CONTAINER(toplevel), vgrid);
1099 gtk_container_add(GTK_CONTAINER(vgrid), notebook);
1100 statusbar = create_statusbar();
1101 gtk_container_add(GTK_CONTAINER(vgrid), statusbar);
1102
1103 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1104 create_main_page(), NULL);
1105 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1106 create_start_page(), NULL);
1107 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1108 create_scenario_page(), NULL);
1109 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1110 create_load_page(), NULL);
1111 gtk_notebook_append_page(GTK_NOTEBOOK(notebook),
1112 create_network_page(), NULL);
1113
1114 editgui_create_widgets();
1115
1116 ingame_votebar = voteinfo_bar_new(FALSE);
1117 g_object_set(ingame_votebar, "margin", 2, NULL);
1118
1119 /* *** everything in the top *** */
1120
1121 page = gtk_scrolled_window_new(NULL, NULL);
1122 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(page),
1123 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1124 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(page),
1125 GTK_SHADOW_ETCHED_IN);
1126 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), page, NULL);
1127
1128 top_vbox = gtk_grid_new();
1129 gtk_orientable_set_orientation(GTK_ORIENTABLE(top_vbox),
1130 GTK_ORIENTATION_VERTICAL);
1131 gtk_grid_set_row_spacing(GTK_GRID(top_vbox), 5);
1132 hgrid = gtk_grid_new();
1133
1134 if (GUI_GTK_OPTION(small_display_layout)) {
1135 /* The window is divided into two horizontal panels: overview +
1136 * civinfo + unitinfo, main view + message window. */
1137 right_vbox = gtk_grid_new();
1138 gtk_orientable_set_orientation(GTK_ORIENTABLE(right_vbox),
1139 GTK_ORIENTATION_VERTICAL);
1140 gtk_container_add(GTK_CONTAINER(hgrid), right_vbox);
1141
1142 paned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
1143 gtk_container_add(GTK_CONTAINER(page), top_vbox);
1144 gtk_container_add(GTK_CONTAINER(top_vbox), hgrid);
1145 gtk_container_add(GTK_CONTAINER(right_vbox), paned);
1146 gtk_container_add(GTK_CONTAINER(right_vbox), ingame_votebar);
1147
1148 /* Overview size designed for small displays (netbooks). */
1149 overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK;
1150 overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK;
1151 } else {
1152 /* The window is divided into two vertical panes: overview +
1153 * + civinfo + unitinfo + main view, message window. */
1154 paned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1155 gtk_container_add(GTK_CONTAINER(page), paned);
1156 gtk_paned_pack1(GTK_PANED(paned), top_vbox, TRUE, FALSE);
1157 gtk_container_add(GTK_CONTAINER(top_vbox), hgrid);
1158
1159 /* Overview size designed for big displays (desktops). */
1160 overview_canvas_store_width = OVERVIEW_CANVAS_STORE_WIDTH;
1161 overview_canvas_store_height = OVERVIEW_CANVAS_STORE_HEIGHT;
1162 }
1163
1164 /* This holds the overview canvas, production info, etc. */
1165 vgrid = gtk_grid_new();
1166 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1167 GTK_ORIENTATION_VERTICAL);
1168 gtk_grid_set_column_spacing(GTK_GRID(vgrid), 3);
1169 /* Put vgrid to the left of anything else in hgrid -- right_vbox is either
1170 * the chat/messages pane, or NULL which is OK */
1171 gtk_grid_attach_next_to(GTK_GRID(hgrid), vgrid, right_vbox,
1172 GTK_POS_LEFT, 1, 1);
1173
1174 /* Overview canvas */
1175 ahbox = detached_widget_new();
1176 gtk_widget_set_hexpand(ahbox, FALSE);
1177 gtk_widget_set_vexpand(ahbox, FALSE);
1178 gtk_container_add(GTK_CONTAINER(vgrid), ahbox);
1179 avbox = detached_widget_fill(ahbox);
1180
1181 overview_scrolled_window = gtk_scrolled_window_new(NULL, NULL);
1182 gtk_container_set_border_width(GTK_CONTAINER (overview_scrolled_window), 1);
1183 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW (overview_scrolled_window),
1184 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
1185
1186 overview_canvas = gtk_drawing_area_new();
1187 gtk_widget_set_halign(overview_canvas, GTK_ALIGN_CENTER);
1188 gtk_widget_set_valign(overview_canvas, GTK_ALIGN_CENTER);
1189 gtk_widget_set_size_request(overview_canvas, overview_canvas_store_width,
1190 overview_canvas_store_height);
1191 gtk_widget_set_size_request(overview_scrolled_window, overview_canvas_store_width,
1192 overview_canvas_store_height);
1193 gtk_widget_set_hexpand(overview_canvas, TRUE);
1194 gtk_widget_set_vexpand(overview_canvas, TRUE);
1195
1196 gtk_widget_add_events(overview_canvas, GDK_EXPOSURE_MASK
1197 |GDK_BUTTON_PRESS_MASK
1198 |GDK_POINTER_MOTION_MASK);
1199 gtk_container_add(GTK_CONTAINER(avbox), overview_scrolled_window);
1200
1201 gtk_container_add(GTK_CONTAINER(overview_scrolled_window),
1202 overview_canvas);
1203
1204 g_signal_connect(overview_canvas, "draw",
1205 G_CALLBACK(overview_canvas_draw), NULL);
1206
1207 g_signal_connect(overview_canvas, "motion_notify_event",
1208 G_CALLBACK(move_overviewcanvas), NULL);
1209
1210 g_signal_connect(overview_canvas, "button_press_event",
1211 G_CALLBACK(butt_down_overviewcanvas), NULL);
1212
1213 /* The rest */
1214
1215 ahbox = detached_widget_new();
1216 gtk_container_add(GTK_CONTAINER(vgrid), ahbox);
1217 gtk_widget_set_hexpand(ahbox, FALSE);
1218 avbox = detached_widget_fill(ahbox);
1219 gtk_widget_set_vexpand(avbox, TRUE);
1220 gtk_widget_set_valign(avbox, GTK_ALIGN_FILL);
1221
1222 /* Info on player's civilization, when game is running. */
1223 frame = gtk_frame_new("");
1224 gtk_container_add(GTK_CONTAINER(avbox), frame);
1225
1226 main_frame_civ_name = frame;
1227
1228 vgrid = gtk_grid_new();
1229 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1230 GTK_ORIENTATION_VERTICAL);
1231 gtk_container_add(GTK_CONTAINER(frame), vgrid);
1232 gtk_widget_set_hexpand(vgrid, TRUE);
1233
1234 ebox = gtk_event_box_new();
1235 gtk_widget_add_events(ebox, GDK_BUTTON_PRESS_MASK);
1236 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1237 g_signal_connect(ebox, "button_press_event",
1238 G_CALLBACK(show_info_popup), NULL);
1239 gtk_container_add(GTK_CONTAINER(vgrid), ebox);
1240
1241 label = gtk_label_new(NULL);
1242 gtk_widget_set_halign(label, GTK_ALIGN_START);
1243 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
1244 gtk_widget_set_margin_left(label, 2);
1245 gtk_widget_set_margin_right(label, 2);
1246 gtk_widget_set_margin_top(label, 2);
1247 gtk_widget_set_margin_bottom(label, 2);
1248 gtk_container_add(GTK_CONTAINER(ebox), label);
1249 main_label_info = label;
1250
1251 /* Production status */
1252 table = gtk_grid_new();
1253 gtk_widget_set_halign(table, GTK_ALIGN_CENTER);
1254 gtk_grid_set_column_homogeneous(GTK_GRID(table), TRUE);
1255 gtk_container_add(GTK_CONTAINER(avbox), table);
1256
1257 /* Citizens for taxrates */
1258 ebox = gtk_event_box_new();
1259 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1260 gtk_grid_attach(GTK_GRID(table), ebox, 0, 0, 10, 1);
1261 econ_ebox = ebox;
1262
1263 table2 = gtk_grid_new();
1264 gtk_container_add(GTK_CONTAINER(ebox), table2);
1265
1266 for (i = 0; i < 10; i++) {
1267 ebox = gtk_event_box_new();
1268 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1269 gtk_widget_add_events(ebox, GDK_BUTTON_PRESS_MASK);
1270
1271 gtk_grid_attach(GTK_GRID(table2), ebox, i, 0, 1, 1);
1272
1273 g_signal_connect(ebox, "button_press_event",
1274 G_CALLBACK(taxrates_callback), GINT_TO_POINTER(i));
1275
1276 spr = i < 5 ? get_tax_sprite(tileset, O_SCIENCE) : get_tax_sprite(tileset, O_GOLD);
1277 econ_label[i] = gtk_image_new_from_surface(spr->surface);
1278 gtk_container_add(GTK_CONTAINER(ebox), econ_label[i]);
1279 }
1280
1281 /* Science, environmental, govt, timeout */
1282 spr = client_research_sprite();
1283 if (spr != NULL) {
1284 bulb_label = gtk_image_new_from_surface(spr->surface);
1285 }
1286 spr = client_warming_sprite();
1287 if (spr != NULL) {
1288 sun_label = gtk_image_new_from_surface(spr->surface);
1289 }
1290 spr = client_cooling_sprite();
1291 if (spr != NULL) {
1292 flake_label = gtk_image_new_from_surface(spr->surface);
1293 }
1294 spr = client_government_sprite();
1295 if (spr != NULL) {
1296 government_label = gtk_image_new_from_surface(spr->surface);
1297 }
1298
1299 for (i = 0; i < 4; i++) {
1300 GtkWidget *w;
1301
1302 ebox = gtk_event_box_new();
1303 gtk_event_box_set_visible_window(GTK_EVENT_BOX(ebox), FALSE);
1304
1305 switch (i) {
1306 case 0:
1307 w = bulb_label;
1308 bulb_ebox = ebox;
1309 break;
1310 case 1:
1311 w = sun_label;
1312 sun_ebox = ebox;
1313 break;
1314 case 2:
1315 w = flake_label;
1316 flake_ebox = ebox;
1317 break;
1318 default:
1319 case 3:
1320 w = government_label;
1321 government_ebox = ebox;
1322 break;
1323 }
1324
1325 gtk_widget_set_halign(w, GTK_ALIGN_START);
1326 gtk_widget_set_valign(w, GTK_ALIGN_START);
1327 gtk_widget_set_margin_left(w, 0);
1328 gtk_widget_set_margin_right(w, 0);
1329 gtk_widget_set_margin_top(w, 0);
1330 gtk_widget_set_margin_bottom(w, 0);
1331 gtk_container_add(GTK_CONTAINER(ebox), w);
1332 gtk_grid_attach(GTK_GRID(table), ebox, i, 1, 1, 1);
1333 }
1334
1335 timeout_label = gtk_label_new("");
1336
1337 frame = gtk_frame_new(NULL);
1338 gtk_grid_attach(GTK_GRID(table), frame, 4, 1, 6, 1);
1339 gtk_container_add(GTK_CONTAINER(frame), timeout_label);
1340
1341
1342 /* Turn done */
1343 turn_done_button = gtk_button_new_with_label(_("Turn Done"));
1344
1345 gtk_grid_attach(GTK_GRID(table), turn_done_button, 0, 2, 10, 1);
1346
1347 g_signal_connect(turn_done_button, "clicked",
1348 G_CALLBACK(end_turn_callback), NULL);
1349
1350 update_turn_done_tooltip();
1351
1352 /* Selected unit status */
1353
1354 unit_info_box = gtk_grid_new();
1355 gtk_widget_set_hexpand(unit_info_box, FALSE);
1356 gtk_orientable_set_orientation(GTK_ORIENTABLE(unit_info_box),
1357 GTK_ORIENTATION_VERTICAL);
1358 gtk_container_add(GTK_CONTAINER(avbox), unit_info_box);
1359
1360 /* In edit mode the unit_info_box widget is replaced by the
1361 * editinfobox, so we need to add a ref here so that it is
1362 * not destroyed when removed from its container.
1363 * See editinfobox_refresh(). */
1364 g_object_ref(unit_info_box);
1365
1366 unit_info_frame = gtk_frame_new("");
1367 gtk_container_add(GTK_CONTAINER(unit_info_box), unit_info_frame);
1368
1369 sw = gtk_scrolled_window_new(NULL, NULL);
1370 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1371 GTK_SHADOW_OUT);
1372 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw),
1373 GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
1374 gtk_container_add(GTK_CONTAINER(unit_info_frame), sw);
1375
1376 label = gtk_label_new(NULL);
1377 gtk_widget_set_hexpand(label, TRUE);
1378 gtk_widget_set_halign(label, GTK_ALIGN_START);
1379 gtk_widget_set_valign(label, GTK_ALIGN_CENTER);
1380 gtk_widget_set_margin_left(label, 2);
1381 gtk_widget_set_margin_right(label, 2);
1382 gtk_widget_set_margin_top(label, 2);
1383 gtk_widget_set_margin_bottom(label, 2);
1384 gtk_container_add(GTK_CONTAINER(sw), label);
1385 unit_info_label = label;
1386
1387 hgrid2 = gtk_grid_new();
1388 gtk_container_add(GTK_CONTAINER(unit_info_box), hgrid2);
1389
1390 table = gtk_grid_new();
1391 g_object_set(table, "margin", 5, NULL);
1392 gtk_container_add(GTK_CONTAINER(hgrid2), table);
1393
1394 gtk_grid_set_row_spacing(GTK_GRID(table), 2);
1395 gtk_grid_set_column_spacing(GTK_GRID(table), 2);
1396
1397 unit_image_table = table;
1398
1399 /* Map canvas, editor toolbar, and scrollbars */
1400
1401 /* The top notebook containing the map view and dialogs. */
1402
1403 top_notebook = gtk_notebook_new();
1404 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(top_notebook), GTK_POS_BOTTOM);
1405 gtk_notebook_set_scrollable(GTK_NOTEBOOK(top_notebook), TRUE);
1406
1407
1408 if (GUI_GTK_OPTION(small_display_layout)) {
1409 gtk_paned_pack1(GTK_PANED(paned), top_notebook, TRUE, FALSE);
1410 } else if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
1411 right_vbox = gtk_grid_new();
1412 gtk_orientable_set_orientation(GTK_ORIENTABLE(right_vbox),
1413 GTK_ORIENTATION_VERTICAL);
1414
1415 gtk_container_add(GTK_CONTAINER(right_vbox), top_notebook);
1416 gtk_container_add(GTK_CONTAINER(right_vbox), ingame_votebar);
1417 gtk_container_add(GTK_CONTAINER(hgrid), right_vbox);
1418 } else {
1419 gtk_container_add(GTK_CONTAINER(hgrid), top_notebook);
1420 }
1421
1422 map_widget = gtk_grid_new();
1423
1424 vgrid = gtk_grid_new();
1425 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1426 GTK_ORIENTATION_VERTICAL);
1427 gtk_container_add(GTK_CONTAINER(vgrid), map_widget);
1428
1429 gtk_container_add(GTK_CONTAINER(vgrid), editgui_get_editbar()->widget);
1430 g_object_set(editgui_get_editbar()->widget, "margin", 4, NULL);
1431
1432 label = gtk_label_new(Q_("?noun:View"));
1433 gtk_notebook_append_page(GTK_NOTEBOOK(top_notebook), vgrid, label);
1434
1435 frame = gtk_frame_new(NULL);
1436 gtk_grid_attach(GTK_GRID(map_widget), frame, 0, 0, 1, 1);
1437
1438 map_canvas = gtk_drawing_area_new();
1439 gtk_widget_set_hexpand(map_canvas, TRUE);
1440 gtk_widget_set_vexpand(map_canvas, TRUE);
1441 gtk_widget_set_size_request(map_canvas, 300, 300);
1442 gtk_widget_set_can_focus(map_canvas, TRUE);
1443
1444 setup_canvas_color_for_state(GTK_STATE_FLAG_NORMAL);
1445 setup_canvas_color_for_state(GTK_STATE_FLAG_ACTIVE);
1446 setup_canvas_color_for_state(GTK_STATE_FLAG_PRELIGHT);
1447 setup_canvas_color_for_state(GTK_STATE_FLAG_SELECTED);
1448 setup_canvas_color_for_state(GTK_STATE_FLAG_INSENSITIVE);
1449 setup_canvas_color_for_state(GTK_STATE_FLAG_INCONSISTENT);
1450 setup_canvas_color_for_state(GTK_STATE_FLAG_FOCUSED);
1451 setup_canvas_color_for_state(GTK_STATE_FLAG_BACKDROP);
1452
1453 gtk_widget_add_events(map_canvas, GDK_EXPOSURE_MASK
1454 |GDK_BUTTON_PRESS_MASK
1455 |GDK_BUTTON_RELEASE_MASK
1456 |GDK_KEY_PRESS_MASK
1457 |GDK_POINTER_MOTION_MASK
1458 |GDK_SCROLL_MASK);
1459
1460 gtk_container_add(GTK_CONTAINER(frame), map_canvas);
1461
1462 map_horizontal_scrollbar =
1463 gtk_scrollbar_new(GTK_ORIENTATION_HORIZONTAL, NULL);
1464 gtk_grid_attach(GTK_GRID(map_widget), map_horizontal_scrollbar, 0, 1, 1, 1);
1465
1466 map_vertical_scrollbar =
1467 gtk_scrollbar_new(GTK_ORIENTATION_VERTICAL, NULL);
1468 gtk_grid_attach(GTK_GRID(map_widget), map_vertical_scrollbar, 1, 0, 1, 1);
1469
1470 g_signal_connect(map_canvas, "draw",
1471 G_CALLBACK(map_canvas_draw), NULL);
1472
1473 g_signal_connect(map_canvas, "configure_event",
1474 G_CALLBACK(map_canvas_configure), NULL);
1475
1476 g_signal_connect(map_canvas, "motion_notify_event",
1477 G_CALLBACK(move_mapcanvas), NULL);
1478
1479 g_signal_connect(toplevel, "enter_notify_event",
1480 G_CALLBACK(leave_mapcanvas), NULL);
1481
1482 g_signal_connect(map_canvas, "button_press_event",
1483 G_CALLBACK(butt_down_mapcanvas), NULL);
1484
1485 g_signal_connect(map_canvas, "button_release_event",
1486 G_CALLBACK(butt_release_mapcanvas), NULL);
1487
1488 g_signal_connect(map_canvas, "scroll_event",
1489 G_CALLBACK(mouse_scroll_mapcanvas), NULL);
1490
1491 g_signal_connect(toplevel, "key_press_event",
1492 G_CALLBACK(toplevel_key_press_handler), NULL);
1493
1494 g_signal_connect(toplevel, "key_release_event",
1495 G_CALLBACK(toplevel_key_release_handler), NULL);
1496
1497 /* *** The message window -- this is a detachable widget *** */
1498
1499 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_MERGED) {
1500 bottom_hpaned = paned;
1501 right_notebook = bottom_notebook = top_notebook;
1502 } else {
1503 GtkWidget *hpaned;
1504
1505 dtach_lowbox = detached_widget_new();
1506 gtk_paned_pack2(GTK_PANED(paned), dtach_lowbox, FALSE, TRUE);
1507 avbox = detached_widget_fill(dtach_lowbox);
1508
1509 vgrid = gtk_grid_new();
1510 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1511 GTK_ORIENTATION_VERTICAL);
1512 if (!GUI_GTK_OPTION(small_display_layout)) {
1513 gtk_container_add(GTK_CONTAINER(vgrid), ingame_votebar);
1514 }
1515 gtk_container_add(GTK_CONTAINER(avbox), vgrid);
1516
1517 if (GUI_GTK_OPTION(small_display_layout)) {
1518 hpaned = gtk_paned_new(GTK_ORIENTATION_VERTICAL);
1519 } else {
1520 hpaned = gtk_paned_new(GTK_ORIENTATION_HORIZONTAL);
1521 }
1522 gtk_container_add(GTK_CONTAINER(vgrid), hpaned);
1523 g_object_set(hpaned, "margin", 4, NULL);
1524 bottom_hpaned = hpaned;
1525
1526 bottom_notebook = gtk_notebook_new();
1527 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(bottom_notebook), GTK_POS_TOP);
1528 gtk_notebook_set_scrollable(GTK_NOTEBOOK(bottom_notebook), TRUE);
1529 gtk_paned_pack1(GTK_PANED(hpaned), bottom_notebook, TRUE, TRUE);
1530
1531 right_notebook = gtk_notebook_new();
1532 g_object_ref(right_notebook);
1533 gtk_notebook_set_tab_pos(GTK_NOTEBOOK(right_notebook), GTK_POS_TOP);
1534 gtk_notebook_set_scrollable(GTK_NOTEBOOK(right_notebook), TRUE);
1535 g_signal_connect(right_notebook, "button-release-event",
1536 G_CALLBACK(right_notebook_button_release), NULL);
1537 if (GUI_GTK_OPTION(message_chat_location) == GUI_GTK_MSGCHAT_SPLIT) {
1538 gtk_paned_pack2(GTK_PANED(hpaned), right_notebook, TRUE, TRUE);
1539 }
1540 }
1541
1542 vgrid = gtk_grid_new();
1543 gtk_orientable_set_orientation(GTK_ORIENTABLE(vgrid),
1544 GTK_ORIENTATION_VERTICAL);
1545
1546 sw = gtk_scrolled_window_new(NULL, NULL);
1547 gtk_scrolled_window_set_shadow_type(GTK_SCROLLED_WINDOW(sw),
1548 GTK_SHADOW_ETCHED_IN);
1549 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(sw), GTK_POLICY_AUTOMATIC,
1550 GTK_POLICY_ALWAYS);
1551 gtk_container_add(GTK_CONTAINER(vgrid), sw);
1552
1553 label = gtk_label_new(_("Chat"));
1554 gtk_notebook_append_page(GTK_NOTEBOOK(bottom_notebook), vgrid, label);
1555
1556 text = gtk_text_view_new_with_buffer(message_buffer);
1557 gtk_widget_set_hexpand(text, TRUE);
1558 gtk_widget_set_vexpand(text, TRUE);
1559 set_message_buffer_view_link_handlers(text);
1560 gtk_text_view_set_editable(GTK_TEXT_VIEW(text), FALSE);
1561 gtk_container_add(GTK_CONTAINER(sw), text);
1562 g_signal_connect(text, "size-allocate",
1563 G_CALLBACK(main_message_area_size_allocate), NULL);
1564
1565 gtk_widget_set_name(text, "chatline");
1566
1567 gtk_text_view_set_wrap_mode(GTK_TEXT_VIEW(text), GTK_WRAP_WORD);
1568 gtk_widget_realize(text);
1569 gtk_text_view_set_left_margin(GTK_TEXT_VIEW(text), 5);
1570
1571 main_message_area = GTK_TEXT_VIEW(text);
1572 if (dtach_lowbox != NULL) {
1573 g_object_set_data(G_OBJECT(dtach_lowbox), "hide-over-reparent", main_message_area);
1574 }
1575
1576 chat_welcome_message(TRUE);
1577
1578 /* the chat line */
1579 view = inputline_toolkit_view_new();
1580 gtk_container_add(GTK_CONTAINER(vgrid), view);
1581 g_object_set(view, "margin", 3, NULL);
1582
1583 button = gtk_check_button_new_with_label(_("Allies Only"));
1584 gtk_button_set_focus_on_click(GTK_BUTTON(button), FALSE);
1585 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
1586 GUI_GTK_OPTION(allied_chat_only));
1587 g_signal_connect(button, "toggled",
1588 G_CALLBACK(allied_chat_button_toggled), NULL);
1589 inputline_toolkit_view_append_button(view, button);
1590 allied_chat_toggle_button = button;
1591
1592 button = gtk_button_new_with_label(_("Clear links"));
1593 g_signal_connect(button, "clicked",
1594 G_CALLBACK(link_marks_clear_all), NULL);
1595 inputline_toolkit_view_append_button(view, button);
1596
1597 /* Other things to take care of */
1598
1599 gtk_widget_show_all(gtk_bin_get_child(GTK_BIN(toplevel)));
1600
1601 if (GUI_GTK_OPTION(enable_tabs)) {
1602 meswin_dialog_popup(FALSE);
1603 }
1604
1605 gtk_notebook_set_current_page(GTK_NOTEBOOK(top_notebook), 0);
1606 gtk_notebook_set_current_page(GTK_NOTEBOOK(bottom_notebook), 0);
1607
1608 if (!GUI_GTK_OPTION(map_scrollbars)) {
1609 gtk_widget_hide(map_horizontal_scrollbar);
1610 gtk_widget_hide(map_vertical_scrollbar);
1611 }
1612}
1613
1614/**********************************************************************/
1617 void ui_init(void)
1618{
1619 log_set_callback(log_callback_utf8);
1620 set_frame_by_frame_animation();
1621}
1622
1623/**********************************************************************/
1626 int main(int argc, char **argv)
1627{
1628 return client_main(argc, argv, FALSE);
1629}
1630
1631/**********************************************************************/
1634 static void migrate_options_from_gtk2(void)
1635{
1636 log_normal(_("Migrating options from gtk2 to gtk3 client"));
1637
1638#define MIGRATE_OPTION(opt) GUI_GTK_OPTION(opt) = gui_options.gui_gtk2_##opt;
1639#define MIGRATE_STR_OPTION(opt) \
1640 strncpy(GUI_GTK_OPTION(opt), gui_options.gui_gtk2_##opt, \
1641 sizeof(GUI_GTK_OPTION(opt)));
1642
1643 /* Default theme name is never migrated */
1644 /* 'fullscreen', 'small_display_layout', and 'message_chat_location'
1645 * not migrated, as (unlike Gtk2), Gtk3-client tries to pick better
1646 * defaults for these in fresh installations based on screen size (see
1647 * adjust_default_options()); so user is probably better served by
1648 * getting these adaptive defaults than whatever they had for Gtk2.
1649 * Since 'fullscreen' isn't migrated, we don't need to worry about
1650 * preserving gui_gtk2_migrated_from_2_5 either. */
1651 MIGRATE_OPTION(map_scrollbars);
1652 MIGRATE_OPTION(dialogs_on_top);
1653 MIGRATE_OPTION(show_task_icons);
1654 MIGRATE_OPTION(enable_tabs);
1655 MIGRATE_OPTION(show_chat_message_time);
1656 MIGRATE_OPTION(new_messages_go_to_top);
1657 MIGRATE_OPTION(show_message_window_buttons);
1658 MIGRATE_OPTION(metaserver_tab_first);
1659 MIGRATE_OPTION(allied_chat_only);
1660 MIGRATE_OPTION(mouse_over_map_focus);
1661 MIGRATE_OPTION(chatline_autocompletion);
1662 MIGRATE_OPTION(citydlg_xsize);
1663 MIGRATE_OPTION(citydlg_ysize);
1664 MIGRATE_OPTION(popup_tech_help);
1665
1666 MIGRATE_STR_OPTION(font_city_label);
1667 MIGRATE_STR_OPTION(font_notify_label);
1668 MIGRATE_STR_OPTION(font_spaceship_label);
1669 MIGRATE_STR_OPTION(font_help_label);
1670 MIGRATE_STR_OPTION(font_help_link);
1671 MIGRATE_STR_OPTION(font_help_text);
1672 MIGRATE_STR_OPTION(font_chatline);
1673 MIGRATE_STR_OPTION(font_beta_label);
1674 MIGRATE_STR_OPTION(font_small);
1675 MIGRATE_STR_OPTION(font_comment_label);
1676 MIGRATE_STR_OPTION(font_city_names);
1677 MIGRATE_STR_OPTION(font_city_productions);
1678 MIGRATE_STR_OPTION(font_reqtree_text);
1679
1680#undef MIGRATE_OPTION
1681#undef MIGRATE_STR_OPTION
1682
1683 GUI_GTK_OPTION(migrated_from_gtk2) = TRUE;
1684}
1685
1686/**********************************************************************/
1689 static void migrate_options_from_2_5(void)
1690{
1691 log_normal(_("Migrating gtk3-client options from freeciv-2.5 options."));
1692
1693 GUI_GTK_OPTION(fullscreen) = gui_options.migrate_fullscreen;
1694
1695 GUI_GTK_OPTION(migrated_from_2_5) = TRUE;
1696}
1697
1698/**********************************************************************/
1701 int ui_main(int argc, char **argv)
1702{
1703 PangoFontDescription *toplevel_font_name;
1704 guint sig;
1705
1706 if (parse_options(argc, argv)) {
1707 char window_name[1024];
1708
1709 /* The locale has already been set in init_nls() and the windows-specific
1710 * locale logic in gtk_init() causes problems with zh_CN (see PR#39475) */
1711 gtk_disable_setlocale();
1712
1713 /* GTK withdraw gtk options. Process GTK arguments */
1714 if (!gtk_init_check(&argc, &argv)) {
1715 log_fatal(_("Failed to open graphical mode."));
1716 exit(EXIT_FAILURE);
1717 }
1718
1719 help_system_init();
1720
1721 toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL);
1722 gtk_window_set_position(GTK_WINDOW(toplevel), GTK_WIN_POS_CENTER);
1723 if (vmode.width > 0 && vmode.height > 0) {
1724 gtk_window_resize(GTK_WINDOW(toplevel), vmode.width, vmode.height);
1725 }
1726 g_signal_connect(toplevel, "key_press_event",
1727 G_CALLBACK(toplevel_handler), NULL);
1728
1729 gtk_window_set_role(GTK_WINDOW(toplevel), "toplevel");
1730 gtk_widget_realize(toplevel);
1731 gtk_widget_set_name(toplevel, "Freeciv");
1732 root_window = gtk_widget_get_window(toplevel);
1733
1734 if (gui_options.first_boot) {
1735 adjust_default_options();
1736 /* We're using fresh defaults for this version of this client,
1737 * so prevent any future migrations from other clients / versions */
1738 GUI_GTK_OPTION(migrated_from_gtk2) = TRUE;
1739 GUI_GTK_OPTION(migrated_from_2_5) = TRUE;
1740 } else {
1741 if (!GUI_GTK_OPTION(migrated_from_gtk2)) {
1742 migrate_options_from_gtk2();
1743 /* We want a fresh look at screen-size-related defaults */
1744 adjust_default_options();
1745 /* We don't ever want to consider pre-2.6 fullscreen option again */
1746 GUI_GTK_OPTION(migrated_from_2_5) = TRUE;
1747 } else if (!GUI_GTK_OPTION(migrated_from_2_5)) {
1748 /* This only affects the fullscreen option, which we don't want
1749 * to touch if adjust_default_options() just adjusted it. */
1750 migrate_options_from_2_5();
1751 }
1752 }
1753
1754 if (GUI_GTK_OPTION(fullscreen)) {
1755 gtk_window_fullscreen(GTK_WINDOW(toplevel));
1756 }
1757
1758 fc_snprintf(window_name, sizeof(window_name), _("Freeciv (%s)"), GUI_NAME_SHORT);
1759 gtk_window_set_title(GTK_WINDOW(toplevel), window_name);
1760
1761 g_signal_connect(toplevel, "delete_event",
1762 G_CALLBACK(quit_dialog_callback), NULL);
1763
1764 /* Disable GTK+ cursor key focus movement */
1765 sig = g_signal_lookup("focus", GTK_TYPE_WIDGET);
1766 g_signal_handlers_disconnect_matched(toplevel, G_SIGNAL_MATCH_ID, sig,
1767 0, 0, 0, 0);
1768 g_signal_connect(toplevel, "focus", G_CALLBACK(toplevel_focus), NULL);
1769
1770 options_iterate(client_optset, poption) {
1771 if (OT_FONT == option_type(poption)) {
1772 /* Force to call the appropriate callback. */
1773 option_changed(poption);
1774 }
1775 } options_iterate_end;
1776
1777 toplevel_font_name = pango_context_get_font_description(
1778 gtk_widget_get_pango_context(toplevel));
1779
1780 if (NULL == city_names_style) {
1781 city_names_style = pango_font_description_copy(toplevel_font_name);
1782 log_error("city_names_style should have been set by options.");
1783 }
1784 if (NULL == city_productions_style) {
1785 city_productions_style = pango_font_description_copy(toplevel_font_name);
1786 log_error("city_productions_style should have been set by options.");
1787 }
1788 if (NULL == reqtree_text_style) {
1789 reqtree_text_style = pango_font_description_copy(toplevel_font_name);
1790 log_error("reqtree_text_style should have been set by options.");
1791 }
1792
1793 tileset_init(tileset);
1794 tileset_load_tiles(tileset);
1795
1796 /* Keep the icon of the executable on Windows (see PR#36491) */
1797#ifndef FREECIV_MSWINDOWS
1798 {
1799 GdkPixbuf *pixbuf = sprite_get_pixbuf(get_icon_sprite(tileset, ICON_FREECIV));
1800
1801 /* Only call this after tileset_load_tiles is called. */
1802 gtk_window_set_icon(GTK_WINDOW(toplevel), pixbuf);
1803 g_object_unref(pixbuf);
1804 }
1805#endif /* FREECIV_MSWINDOWS */
1806
1807 setup_widgets();
1808 load_cursors();
1809 cma_fe_init();
1810 diplomacy_dialog_init();
1811 luaconsole_dialog_init();
1812 happiness_dialog_init();
1813 citizens_dialog_init();
1814 intel_dialog_init();
1815 spaceship_dialog_init();
1816 chatline_init();
1817 init_mapcanvas_and_overview();
1818
1819 tileset_use_preferred_theme(tileset);
1820
1821 gtk_widget_show(toplevel);
1822
1823 /* Assumes toplevel showing */
1824 set_client_state(C_S_DISCONNECTED);
1825
1826 /* Assumes client_state is set */
1827 timer_id = g_timeout_add(TIMER_INTERVAL, timer_callback, NULL);
1828
1829 gui_up = TRUE;
1830 gtk_main();
1831 gui_up = FALSE;
1832
1833 destroy_server_scans();
1834 free_mapcanvas_and_overview();
1835 spaceship_dialog_done();
1836 intel_dialog_done();
1837 citizens_dialog_done();
1838 luaconsole_dialog_done();
1839 happiness_dialog_done();
1840 diplomacy_dialog_done();
1841 cma_fe_done();
1842 free_unit_table();
1843
1844 /* We have extra ref for unit_info_box that has protected
1845 * it from getting destroyed when editinfobox_refresh()
1846 * moves widgets around. Free that extra ref here. */
1847 g_object_unref(unit_info_box);
1848
1849 editgui_free();
1850 gtk_widget_destroy(toplevel_tabs);
1851 gtk_widget_destroy(toplevel);
1852 menus_free();
1853 message_buffer = NULL; /* Result of destruction of everything */
1854 tileset_free_tiles(tileset);
1855 }
1856
1857 return EXIT_SUCCESS;
1858}
1859
1860/**********************************************************************/
1863 bool is_gui_up(void)
1864{
1865 return gui_up;
1866}
1867
1868/**********************************************************************/
1871 void ui_exit(void)
1872{
1873 if (message_buffer != NULL) {
1874 g_object_unref(message_buffer);
1875 message_buffer = NULL;
1876 }
1877}
1878
1879/**********************************************************************/
1882 enum gui_type get_gui_type(void)
1883{
1884 return GUI_GTK3;
1885}
1886
1887/**********************************************************************/
1890 void sound_bell(void)
1891{
1892 gdk_display_beep(gdk_display_get_default());
1893}
1894
1895/**********************************************************************/
1901 void set_unit_icon(int idx, struct unit *punit)
1902{
1903 GtkWidget *w;
1904
1905 fc_assert_ret(idx >= -1 && idx < num_units_below);
1906
1907 if (idx == -1) {
1908 w = unit_image;
1909 unit_id_top = punit ? punit->id : 0;
1910 } else {
1911 w = unit_below_image[idx];
1912 unit_ids[idx] = punit ? punit->id : 0;
1913 }
1914
1915 if (!w) {
1916 return;
1917 }
1918
1919 if (punit) {
1920 put_unit_image(punit, GTK_IMAGE(w), -1);
1921 } else {
1922 gtk_image_clear(GTK_IMAGE(w));
1923 }
1924}
1925
1926/**********************************************************************/
1931 void set_unit_icons_more_arrow(bool onoff)
1932{
1933 static bool showing = FALSE;
1934
1935 if (!more_arrow_pixmap_button) {
1936 return;
1937 }
1938
1939 if (onoff && !showing) {
1940 gtk_widget_show(more_arrow_pixmap_button);
1941 showing = TRUE;
1942 } else if (!onoff && showing) {
1943 gtk_widget_hide(more_arrow_pixmap_button);
1944 showing = FALSE;
1945 }
1946}
1947
1948/**********************************************************************/
1954 void real_focus_units_changed(void)
1955{
1956 goto_dialog_focus_units_changed();
1957}
1958
1959/**********************************************************************/
1963 static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev,
1964 gpointer data)
1965{
1966 int i = GPOINTER_TO_INT(data);
1967 struct unit *punit;
1968
1969 if (i == -1) {
1970 punit = game_unit_by_number(unit_id_top);
1971 if (punit && unit_is_in_focus(punit)) {
1972 /* Clicking on the currently selected unit will center it. */
1973 center_tile_mapcanvas(unit_tile(punit));
1974 }
1975 return TRUE;
1976 }
1977
1978 if (unit_ids[i] == 0) /* no unit displayed at this place */
1979 return TRUE;
1980
1981 punit = game_unit_by_number(unit_ids[i]);
1982 if (NULL != punit && unit_owner(punit) == client.conn.playing) {
1983 /* Unit shouldn't be NULL but may be owned by an ally. */
1984 unit_focus_set(punit);
1985 }
1986
1987 return TRUE;
1988}
1989
1990/**********************************************************************/
1994 static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev,
1995 gpointer data)
1996{
1997 struct unit *punit = game_unit_by_number(unit_id_top);
1998
1999 if (punit) {
2000 unit_select_dialog_popup(unit_tile(punit));
2001 }
2002
2003 return TRUE;
2004}
2005
2006/**********************************************************************/
2009 static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data)
2010{
2011 gtk_grab_remove(w);
2012 gdk_device_ungrab(ev->device, ev->time);
2013 gtk_widget_destroy(w);
2014 return FALSE;
2015}
2016
2017/**********************************************************************/
2020 static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
2021{
2022 if (ev->button == 1) {
2023 GtkWidget *p;
2024
2025 p = gtk_window_new(GTK_WINDOW_POPUP);
2026 gtk_container_set_border_width(GTK_CONTAINER(p), 4);
2027 gtk_window_set_transient_for(GTK_WINDOW(p), GTK_WINDOW(toplevel));
2028 gtk_window_set_position(GTK_WINDOW(p), GTK_WIN_POS_MOUSE);
2029
2030 gtk_widget_new(GTK_TYPE_LABEL, "GtkWidget::parent", p,
2031 "GtkLabel::label", get_info_label_text_popup(),
2032 "GtkWidget::visible", TRUE,
2033 NULL);
2034 gtk_widget_show(p);
2035
2036 gdk_device_grab(ev->device, gtk_widget_get_window(p),
2037 GDK_OWNERSHIP_NONE, TRUE, GDK_BUTTON_RELEASE_MASK, NULL,
2038 ev->time);
2039 gtk_grab_add(p);
2040
2041 g_signal_connect_after(p, "button_release_event",
2042 G_CALLBACK(show_info_button_release), NULL);
2043 }
2044
2045 return TRUE;
2046}
2047
2048/**********************************************************************/
2051 static void end_turn_callback(GtkWidget *w, gpointer data)
2052{
2053 gtk_widget_set_sensitive(turn_done_button, FALSE);
2054 user_ended_turn();
2055}
2056
2057/**********************************************************************/
2060 static gboolean get_net_input(GIOChannel *source, GIOCondition condition,
2061 gpointer data)
2062{
2063 input_from_server(g_io_channel_unix_get_fd(source));
2064
2065 return TRUE;
2066}
2067
2068/**********************************************************************/
2071 static void set_wait_for_writable_socket(struct connection *pc,
2072 bool socket_writable)
2073{
2074 static bool previous_state = FALSE;
2075
2076 fc_assert_ret(pc == &client.conn);
2077
2078 if (previous_state == socket_writable) {
2079 return;
2080 }
2081
2082 log_debug("set_wait_for_writable_socket(%d)", socket_writable);
2083
2084 g_source_remove(srv_id);
2085 srv_id = g_io_add_watch(srv_channel,
2086 G_IO_IN | (socket_writable ? G_IO_OUT : 0) | G_IO_ERR,
2087 get_net_input,
2088 NULL);
2089
2090 previous_state = socket_writable;
2091}
2092
2093/**********************************************************************/
2097 void add_net_input(int sock)
2098{
2099#ifdef FREECIV_MSWINDOWS
2100 srv_channel = g_io_channel_win32_new_socket(sock);
2101#else
2102 srv_channel = g_io_channel_unix_new(sock);
2103#endif
2104 srv_id = g_io_add_watch(srv_channel,
2105 G_IO_IN | G_IO_ERR,
2106 get_net_input,
2107 NULL);
2108 client.conn.notify_of_writable_data = set_wait_for_writable_socket;
2109}
2110
2111/**********************************************************************/
2115 void remove_net_input(void)
2116{
2117 g_source_remove(srv_id);
2118 g_io_channel_unref(srv_channel);
2119 gdk_window_set_cursor(root_window, NULL);
2120}
2121
2122/**********************************************************************/
2126 static void quit_dialog_response(GtkWidget *dialog, gint response)
2127{
2128 gtk_widget_destroy(dialog);
2129 if (response == GTK_RESPONSE_YES) {
2130 start_quitting();
2131 if (client.conn.used) {
2132 disconnect_from_server();
2133 }
2134 quit_gtk_main();
2135 }
2136}
2137
2138/**********************************************************************/
2141 void quit_gtk_main(void)
2142{
2143 /* Quit gtk main loop. After this it will return to finish
2144 * ui_main() */
2145
2146 gtk_main_quit();
2147}
2148
2149/**********************************************************************/
2153 void popup_quit_dialog(void)
2154{
2155 static GtkWidget *dialog;
2156
2157 if (!dialog) {
2158 dialog = gtk_message_dialog_new(NULL,
2159 0,
2160 GTK_MESSAGE_WARNING,
2161 GTK_BUTTONS_YES_NO,
2162 _("Are you sure you want to quit?"));
2163 setup_dialog(dialog, toplevel);
2164
2165 gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_MOUSE);
2166
2167 g_signal_connect(dialog, "response",
2168 G_CALLBACK(quit_dialog_response), NULL);
2169 g_signal_connect(dialog, "destroy",
2170 G_CALLBACK(gtk_widget_destroyed), &dialog);
2171 }
2172
2173 gtk_window_present(GTK_WINDOW(dialog));
2174}
2175
2176/**********************************************************************/
2179 static gboolean quit_dialog_callback(void)
2180{
2181 popup_quit_dialog();
2182 /* Stop emission of event. */
2183 return TRUE;
2184}
2185
2186 struct callback {
2187 void (*callback)(void *data);
2188 void *data;
2189};
2190
2191/**********************************************************************/
2194 static gboolean idle_callback_wrapper(gpointer data)
2195{
2196 struct callback *cb = data;
2197
2198 (cb->callback)(cb->data);
2199 free(cb);
2200
2201 return FALSE;
2202}
2203
2204/**********************************************************************/
2209 void add_idle_callback(void (callback)(void *), void *data)
2210{
2211 struct callback *cb = fc_malloc(sizeof(*cb));
2212
2213 cb->callback = callback;
2214 cb->data = data;
2215 g_idle_add(idle_callback_wrapper, cb);
2216}
2217
2218/**********************************************************************/
2222 static void allied_chat_only_callback(struct option *poption)
2223{
2224 GtkWidget *button;
2225
2226 button = allied_chat_toggle_button;
2227 fc_assert_ret(button != NULL);
2228 fc_assert_ret(GTK_IS_TOGGLE_BUTTON(button));
2229
2230 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2231 option_bool_get(poption));
2232}
2233
2234/**********************************************************************/
2237 void fullscreen_opt_refresh(struct option *poption)
2238{
2239 if (GUI_GTK_OPTION(fullscreen)) {
2240 gtk_window_fullscreen(GTK_WINDOW(toplevel));
2241 } else {
2242 gtk_window_unfullscreen(GTK_WINDOW(toplevel));
2243 }
2244}
2245
2246/**********************************************************************/
2249 static void apply_city_names_font(struct option *poption)
2250{
2251 gui_update_font_full(option_font_target(poption),
2252 option_font_get(poption),
2253 &city_names_style);
2254 update_city_descriptions();
2255}
2256
2257/**********************************************************************/
2260 static void apply_city_productions_font(struct option *poption)
2261{
2262 gui_update_font_full(option_font_target(poption),
2263 option_font_get(poption),
2264 &city_productions_style);
2265 update_city_descriptions();
2266}
2267
2268/**********************************************************************/
2271 static void apply_reqtree_text_font(struct option *poption)
2272{
2273 gui_update_font_full(option_font_target(poption),
2274 option_font_get(poption),
2275 &reqtree_text_style);
2276 science_report_dialog_redraw();
2277}
2278
2279/**********************************************************************/
2283 void options_extra_init(void)
2284{
2285 struct option *poption;
2286
2287#define option_var_set_callback(var, callback) \
2288 if ((poption = optset_option_by_name(client_optset, GUI_GTK_OPTION_STR(var)))) { \
2289 option_set_changed_callback(poption, callback); \
2290 } else { \
2291 log_error("Didn't find option %s!", GUI_GTK_OPTION_STR(var)); \
2292 }
2293
2294 option_var_set_callback(allied_chat_only,
2295 allied_chat_only_callback);
2296 option_var_set_callback(fullscreen,
2297 fullscreen_opt_refresh);
2298
2299 option_var_set_callback(font_city_names,
2300 apply_city_names_font);
2301 option_var_set_callback(font_city_productions,
2302 apply_city_productions_font);
2303 option_var_set_callback(font_reqtree_text,
2304 apply_reqtree_text_font);
2305#undef option_var_set_callback
2306}
2307
2308/**********************************************************************/
2312 void refresh_chat_buttons(void)
2313{
2314 GtkWidget *button;
2315
2316 button = allied_chat_toggle_button;
2317 fc_assert_ret(button != NULL);
2318 fc_assert_ret(GTK_IS_TOGGLE_BUTTON(button));
2319
2320 /* Hide the "Allies Only" button for local games. */
2321 if (is_server_running()) {
2322 gtk_widget_hide(button);
2323 } else {
2324 gtk_widget_show(button);
2325 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button),
2326 GUI_GTK_OPTION(allied_chat_only));
2327 }
2328}
2329
2330/**********************************************************************/
2333 static void allied_chat_button_toggled(GtkToggleButton *button,
2334 gpointer user_data)
2335{
2336 GUI_GTK_OPTION(allied_chat_only) = gtk_toggle_button_get_active(button);
2337}
2338
2339/**********************************************************************/
2342 void insert_client_build_info(char *outbuf, size_t outlen)
2343{
2344 cat_snprintf(outbuf, outlen, _("\nBuilt against gtk+ %d.%d.%d, using %d.%d.%d"
2345 "\nBuilt against glib %d.%d.%d, using %d.%d.%d"),
2346 GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION,
2347 gtk_get_major_version(), gtk_get_minor_version(), gtk_get_micro_version(),
2348 GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION,
2349 glib_major_version, glib_minor_version, glib_micro_version);
2350}
2351
2352/**********************************************************************/
2355 int screen_width(void)
2356{
2357 GdkScreen *screen;
2358
2359 if (vmode.width > 0) {
2360 return vmode.width;
2361 }
2362
2363 screen = gdk_screen_get_default();
2364
2365 if (screen == NULL) {
2366 return 0;
2367 }
2368
2369 return gdk_screen_get_width(screen);
2370}
2371
2372/**********************************************************************/
2375 int screen_height(void)
2376{
2377 GdkScreen *screen;
2378
2379 if (vmode.height > 0) {
2380 return vmode.height;
2381 }
2382
2383 screen = gdk_screen_get_default();
2384
2385 if (screen == NULL) {
2386 return 0;
2387 }
2388
2389 return gdk_screen_get_height(screen);
2390}
2391
2392/**********************************************************************/
2395 struct video_mode *resolution_request_get(void)
2396{
2397 if (vmode.width > 0 && vmode.height > 0) {
2398 return &vmode;
2399 }
2400
2401 return NULL;
2402}
2403
2404/**********************************************************************/
2407 static void adjust_default_options(void)
2408{
2409 int scr_height = screen_height();
2410
2411 if (scr_height > 0) {
2412 /* Adjust these options only if we do know the screen height. */
2413
2414 if (scr_height <= 480) {
2415 /* Freeciv is practically unusable outside fullscreen mode in so
2416 * small display */
2417 log_verbose("Changing default to fullscreen due to very small screen");
2418 GUI_GTK_OPTION(fullscreen) = TRUE;
2419 }
2420 if (scr_height < 1024) {
2421 /* This is a small display */
2422 log_verbose("Defaulting to small widget layout due to small screen");
2423 GUI_GTK_OPTION(small_display_layout) = TRUE;
2424 log_verbose("Defaulting to merged messages/chat due to small screen");
2425 GUI_GTK_OPTION(message_chat_location) = GUI_GTK_MSGCHAT_MERGED;
2426 }
2427 }
2428}
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
client_is_observer
bool client_is_observer(void)
Definition client_main.c:1086
real_timer_callback
double real_timer_callback(void)
Definition client_main.c:1183
client_main
int client_main(int argc, char *argv[], bool postpone_tileset)
Definition client_main.c:344
user_ended_turn
void user_ended_turn(void)
Definition client_main.c:801
client
struct civclient client
Definition client_main.c:149
start_quitting
void start_quitting(void)
Definition client_main.c:1645
set_client_state
void set_client_state(enum client_states newstate)
Definition client_main.c:847
can_client_change_view
bool can_client_change_view(void)
Definition client_main.c:1313
client_main.h
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:1299
client_warming_sprite
struct sprite * client_warming_sprite(void)
Definition climisc.c:371
client_cooling_sprite
struct sprite * client_cooling_sprite(void)
Definition climisc.c:388
client_research_sprite
struct sprite * client_research_sprite(void)
Definition climisc.c:348
client_government_sprite
struct sprite * client_government_sprite(void)
Definition climisc.c:406
climisc.h
input_from_server
void input_from_server(int fd)
Definition clinet.c:406
disconnect_from_server
void disconnect_from_server(void)
Definition clinet.c:305
clinet.h
get_color
struct color * get_color(const struct tileset *t, enum color_std stdcolor)
Definition colors_common.c:100
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:3132
unit_is_in_focus
bool unit_is_in_focus(const struct unit *punit)
Definition control.c:384
key_cancel_action
void key_cancel_action(void)
Definition control.c:3071
num_units_below
int num_units_below
Definition control.c:76
unit_focus_set
void unit_focus_set(struct unit *punit)
Definition control.c:502
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:3124
update_unit_pix_label
void update_unit_pix_label(struct unit_list *punitlist)
Definition control.c:966
key_unit_move
void key_unit_move(enum direction8 gui_dir)
Definition control.c:3153
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:406
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:1188
key_center_capital
void key_center_capital(void)
Definition control.c:3107
control.h
MAX_NUM_UNITS_BELOW
#define MAX_NUM_UNITS_BELOW
Definition control.h:285
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:73
editor_is_active
bool editor_is_active(void)
Definition editor.c:346
editor.h
event
enum event_type event
Definition events.c:81
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:91
O_GOLD
@ O_GOLD
Definition fc_types.h:91
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:111
game.h
government.h
inputline_has_focus
bool inputline_has_focus(void)
Definition chatline.c:71
inputline_toolkit_view_append_button
void inputline_toolkit_view_append_button(GtkWidget *toolkit_view, GtkWidget *button)
Definition chatline.c:1288
inputline_toolkit_view_new
GtkWidget * inputline_toolkit_view_new(void)
Definition chatline.c:1266
set_message_buffer_view_link_handlers
void set_message_buffer_view_link_handlers(GtkWidget *view)
Definition chatline.c:744
inputline_is_visible
bool inputline_is_visible(void)
Definition chatline.c:87
chatline_init
void chatline_init(void)
Definition chatline.c:1298
inputline_grab_focus
void inputline_grab_focus(void)
Definition chatline.c:79
chatline_scroll_to_bottom
void chatline_scroll_to_bottom(bool delayed)
Definition chatline.c:1006
citizens_dialog_init
void citizens_dialog_init(void)
Definition citizensinfo.c:267
citizens_dialog_done
void citizens_dialog_done(void)
Definition citizensinfo.c:275
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:382
taxrates_callback
gboolean taxrates_callback(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition dialogs.c:1434
diplomacy_dialog_init
void diplomacy_dialog_init(void)
Definition diplodlg.c:1173
diplomacy_dialog_done
void diplomacy_dialog_done(void)
Definition diplodlg.c:1182
handle_edit_key_release
gboolean handle_edit_key_release(GdkEventKey *ev)
Definition editgui.c:1779
handle_edit_key_press
gboolean handle_edit_key_press(GdkEventKey *ev)
Definition editgui.c:1661
editgui_create_widgets
void editgui_create_widgets(void)
Definition editgui.c:1821
editgui_get_editbar
struct editbar * editgui_get_editbar(void)
Definition editgui.c:1787
editgui_free
void editgui_free(void)
Definition editgui.c:1834
goto_dialog_focus_units_changed
void goto_dialog_focus_units_changed(void)
Definition gotodlg.c:540
source
static GtkWidget * source
Definition gotodlg.c:58
load_cursors
void load_cursors(void)
Definition graphics.c:78
map_vertical_scrollbar
GtkWidget * map_vertical_scrollbar
Definition gui_main.c:108
ui_main
int ui_main(int argc, char **argv)
Definition gui_main.c:1701
client_string
const char * client_string
Definition gui_main.c:104
message_buffer
GtkTextBuffer * message_buffer
Definition gui_main.c:177
log_gtk_warns
static void log_gtk_warns(const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data)
Definition gui_main.c:276
quit_dialog_response
static void quit_dialog_response(GtkWidget *dialog, gint response)
Definition gui_main.c:2126
real_focus_units_changed
void real_focus_units_changed(void)
Definition gui_main.c:1954
set_unit_icons_more_arrow
void set_unit_icons_more_arrow(bool onoff)
Definition gui_main.c:1931
print_usage
static void print_usage(void)
Definition gui_main.c:249
OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK
#define OVERVIEW_CANVAS_STORE_WIDTH_NETBOOK
Definition gui_main.c:115
option_var_set_callback
#define option_var_set_callback(var, callback)
select_unit_image_callback
static gboolean select_unit_image_callback(GtkWidget *w, GdkEvent *ev, gpointer data)
Definition gui_main.c:1963
quit_dialog_callback
static gboolean quit_dialog_callback(void)
Definition gui_main.c:2179
srv_channel
static GIOChannel * srv_channel
Definition gui_main.c:181
main_label_info
GtkWidget * main_label_info
Definition gui_main.c:137
bottom_notebook
GtkWidget * bottom_notebook
Definition gui_main.c:128
unit_info_label
GtkWidget * unit_info_label
Definition gui_main.c:150
timer_callback
static gboolean timer_callback(gpointer data)
Definition gui_main.c:236
resolution_request_get
struct video_mode * resolution_request_get(void)
Definition gui_main.c:2395
set_unit_icon
void set_unit_icon(int idx, struct unit *punit)
Definition gui_main.c:1901
unit_ids
static int unit_ids[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:174
timeout_label
GtkWidget * timeout_label
Definition gui_main.c:147
gui_up
static bool gui_up
Definition gui_main.c:185
srv_id
static guint srv_id
Definition gui_main.c:182
mouse_scroll_mapcanvas
static gboolean mouse_scroll_mapcanvas(GtkWidget *w, GdkEventScroll *ev)
Definition gui_main.c:690
city_productions_style
PangoFontDescription * city_productions_style
Definition gui_main.c:133
overview_scrolled_window
GtkWidget * overview_scrolled_window
Definition gui_main.c:111
more_arrow_pixmap
static GtkWidget * more_arrow_pixmap
Definition gui_main.c:169
detached_widget_fill
static GtkWidget * detached_widget_fill(GtkWidget *tearbox)
Definition gui_main.c:817
enable_menus
void enable_menus(bool enable)
Definition gui_main.c:1000
select_more_arrow_pixmap_callback
static gboolean select_more_arrow_pixmap_callback(GtkWidget *w, GdkEvent *ev, gpointer data)
Definition gui_main.c:1994
top_notebook
GtkWidget * top_notebook
Definition gui_main.c:128
propagate_keypress
static gboolean propagate_keypress(GtkWidget *w, GdkEvent *ev)
Definition gui_main.c:758
MIGRATE_STR_OPTION
#define MIGRATE_STR_OPTION(opt)
econ_ebox
GtkWidget * econ_ebox
Definition gui_main.c:154
unit_info_box
GtkWidget * unit_info_box
Definition gui_main.c:151
ui_exit
void ui_exit(void)
Definition gui_main.c:1871
get_gui_type
enum gui_type get_gui_type(void)
Definition gui_main.c:1882
detached_widget_new
static GtkWidget * detached_widget_new(void)
Definition gui_main.c:805
cur_y
gint cur_y
Definition gui_main.c:183
main
int main(int argc, char **argv)
Definition gui_main.c:1626
fullscreen_opt_refresh
void fullscreen_opt_refresh(struct option *poption)
Definition gui_main.c:2237
main_message_area_size_allocate
static void main_message_area_size_allocate(GtkWidget *widget, GtkAllocation *allocation, gpointer data)
Definition gui_main.c:349
toplevel_handler
static gboolean toplevel_handler(GtkWidget *w, GdkEvent *ev, gpointer data)
Definition gui_main.c:383
ui_init
void ui_init(void)
Definition gui_main.c:1617
unit_below_image_button
static GtkWidget * unit_below_image_button[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:168
free_unit_table
static void free_unit_table(void)
Definition gui_main.c:943
idle_callback_wrapper
static gboolean idle_callback_wrapper(gpointer data)
Definition gui_main.c:2194
apply_city_names_font
static void apply_city_names_font(struct option *poption)
Definition gui_main.c:2249
apply_city_productions_font
static void apply_city_productions_font(struct option *poption)
Definition gui_main.c:2260
unit_below_image
static GtkWidget * unit_below_image[MAX_NUM_UNITS_BELOW]
Definition gui_main.c:167
tearoff_destroy
static void tearoff_destroy(GtkWidget *w, gpointer data)
Definition gui_main.c:742
government_label
GtkWidget * government_label
Definition gui_main.c:146
sun_label
GtkWidget * sun_label
Definition gui_main.c:144
city_names_style
PangoFontDescription * city_names_style
Definition gui_main.c:132
refresh_chat_buttons
void refresh_chat_buttons(void)
Definition gui_main.c:2312
map_canvas_focus
gboolean map_canvas_focus(void)
Definition gui_main.c:366
turn_done_button
GtkWidget * turn_done_button
Definition gui_main.c:148
bottom_hpaned
static GtkWidget * bottom_hpaned
Definition gui_main.c:130
timer_id
static gint timer_id
Definition gui_main.c:180
main_menubar
static GtkWidget * main_menubar
Definition gui_main.c:163
screen_width
int screen_width(void)
Definition gui_main.c:2355
scroll_panel
GtkWidget * scroll_panel
Definition gui_main.c:140
end_turn_callback
static void end_turn_callback(GtkWidget *w, gpointer data)
Definition gui_main.c:2051
OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK
#define OVERVIEW_CANVAS_STORE_HEIGHT_NETBOOK
Definition gui_main.c:116
log_callback_utf8
static void log_callback_utf8(enum log_level level, const char *message, bool file_too)
Definition gui_main.c:224
add_idle_callback
void add_idle_callback(void(callback)(void *), void *data)
Definition gui_main.c:2209
show_info_popup
static gboolean show_info_popup(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition gui_main.c:2020
reset_unit_table
void reset_unit_table(void)
Definition gui_main.c:971
key_press_map_canvas
static gboolean key_press_map_canvas(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:407
unit_info_frame
GtkWidget * unit_info_frame
Definition gui_main.c:152
options_extra_init
void options_extra_init(void)
Definition gui_main.c:2283
top_vbox
GtkWidget * top_vbox
Definition gui_main.c:127
allied_chat_only_callback
static void allied_chat_only_callback(struct option *poption)
Definition gui_main.c:2222
root_window
GdkWindow * root_window
Definition gui_main.c:125
adjust_default_options
static void adjust_default_options(void)
Definition gui_main.c:2407
set_wait_for_writable_socket
static void set_wait_for_writable_socket(struct connection *pc, bool socket_writable)
Definition gui_main.c:2071
more_arrow_pixmap_button
static GtkWidget * more_arrow_pixmap_button
Definition gui_main.c:170
ahbox
GtkWidget * ahbox
Definition gui_main.c:139
apply_reqtree_text_font
static void apply_reqtree_text_font(struct option *poption)
Definition gui_main.c:2271
show_info_button_release
static gboolean show_info_button_release(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition gui_main.c:2009
is_gui_up
bool is_gui_up(void)
Definition gui_main.c:1863
toplevel_focus
static gboolean toplevel_focus(GtkWidget *w, GtkDirectionType arg)
Definition gui_main.c:322
reqtree_text_style
PangoFontDescription * reqtree_text_style
Definition gui_main.c:134
sun_ebox
GtkWidget * sun_ebox
Definition gui_main.c:156
bulb_ebox
GtkWidget * bulb_ebox
Definition gui_main.c:155
flake_label
GtkWidget * flake_label
Definition gui_main.c:145
avbox
GtkWidget * avbox
Definition gui_main.c:139
cur_x
gint cur_x
Definition gui_main.c:183
insert_client_build_info
void insert_client_build_info(char *outbuf, size_t outlen)
Definition gui_main.c:2342
unit_image_button
static GtkWidget * unit_image_button
Definition gui_main.c:166
unit_image_table
static GtkWidget * unit_image_table
Definition gui_main.c:164
right_notebook_button_release
static gboolean right_notebook_button_release(GtkWidget *widget, GdkEventButton *event)
Definition gui_main.c:1023
bulb_label
GtkWidget * bulb_label
Definition gui_main.c:143
overview_canvas
GtkWidget * overview_canvas
Definition gui_main.c:110
toplevel
GtkWidget * toplevel
Definition gui_main.c:124
setup_widgets
static void setup_widgets(void)
Definition gui_main.c:1073
OVERVIEW_CANVAS_STORE_WIDTH
#define OVERVIEW_CANVAS_STORE_WIDTH
Definition gui_main.c:117
toplevel_key_release_handler
static gboolean toplevel_key_release_handler(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:588
remove_net_input
void remove_net_input(void)
Definition gui_main.c:2115
map_horizontal_scrollbar
GtkWidget * map_horizontal_scrollbar
Definition gui_main.c:107
setup_canvas_color_for_state
static void setup_canvas_color_for_state(GtkStateFlags state)
Definition gui_main.c:1043
map_canvas
GtkWidget * map_canvas
Definition gui_main.c:106
toplevel_key_press_handler
static gboolean toplevel_key_press_handler(GtkWidget *w, GdkEventKey *ev, gpointer data)
Definition gui_main.c:606
sound_bell
void sound_bell(void)
Definition gui_main.c:1890
migrate_options_from_gtk2
static void migrate_options_from_gtk2(void)
Definition gui_main.c:1634
econ_label
GtkWidget * econ_label[10]
Definition gui_main.c:142
government_ebox
GtkWidget * government_ebox
Definition gui_main.c:158
migrate_options_from_2_5
static void migrate_options_from_2_5(void)
Definition gui_main.c:1689
popup_quit_dialog
void popup_quit_dialog(void)
Definition gui_main.c:2153
gui_character_encoding
const char *const gui_character_encoding
Definition gui_main.c:160
unit_id_top
static int unit_id_top
Definition gui_main.c:173
get_net_input
static gboolean get_net_input(GIOChannel *source, GIOCondition condition, gpointer data)
Definition gui_main.c:2060
more_arrow_pixmap_container
static GtkWidget * more_arrow_pixmap_container
Definition gui_main.c:171
map_widget
GtkWidget * map_widget
Definition gui_main.c:129
right_notebook
GtkWidget * right_notebook
Definition gui_main.c:128
quit_gtk_main
void quit_gtk_main(void)
Definition gui_main.c:2141
allied_chat_button_toggled
static void allied_chat_button_toggled(GtkToggleButton *button, gpointer user_data)
Definition gui_main.c:2333
vmode
static struct video_mode vmode
Definition gui_main.c:187
add_net_input
void add_net_input(int sock)
Definition gui_main.c:2097
toplevel_tabs
GtkWidget * toplevel_tabs
Definition gui_main.c:126
allied_chat_toggle_button
static GtkWidget * allied_chat_toggle_button
Definition gui_main.c:178
flake_ebox
GtkWidget * flake_ebox
Definition gui_main.c:157
overview_canvas_store_width
int overview_canvas_store_width
Definition gui_main.c:121
update_turn_done_tooltip
void update_turn_done_tooltip(void)
Definition gui_main.c:1054
tearoff_callback
static void tearoff_callback(GtkWidget *b, gpointer data)
Definition gui_main.c:769
unit_image
static GtkWidget * unit_image
Definition gui_main.c:165
main_message_area
GtkTextView * main_message_area
Definition gui_main.c:176
overview_canvas_store_height
int overview_canvas_store_height
Definition gui_main.c:122
screen_height
int screen_height(void)
Definition gui_main.c:2375
parse_options
static bool parse_options(int argc, char **argv)
Definition gui_main.c:286
conn_box
GtkWidget * conn_box
Definition gui_main.c:139
OVERVIEW_CANVAS_STORE_HEIGHT
#define OVERVIEW_CANVAS_STORE_HEIGHT
Definition gui_main.c:119
main_frame_civ_name
GtkWidget * main_frame_civ_name
Definition gui_main.c:136
MIGRATE_OPTION
#define MIGRATE_OPTION(opt)
gui_use_transliteration
const bool gui_use_transliteration
Definition gui_main.c:161
populate_unit_image_table
static void populate_unit_image_table(void)
Definition gui_main.c:841
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
setup_dialog
void setup_dialog(GtkWidget *shell, GtkWidget *parent)
Definition gui_stuff.c:281
gui_update_font_full
void gui_update_font_full(const char *font_name, const char *font_value, PangoFontDescription **font_desc)
Definition gui_stuff.c:1070
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:156
intel_dialog_done
void intel_dialog_done(void)
Definition inteldlg.c:127
intel_dialog_init
void intel_dialog_init(void)
Definition inteldlg.c:118
luaconsole_dialog_init
void luaconsole_dialog_init(void)
Definition luaconsole.c:83
luaconsole_dialog_done
void luaconsole_dialog_done(void)
Definition luaconsole.c:101
butt_release_mapcanvas
gboolean butt_release_mapcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition mapctrl.c:216
move_overviewcanvas
gboolean move_overviewcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:458
butt_down_overviewcanvas
gboolean butt_down_overviewcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition mapctrl.c:467
butt_down_mapcanvas
gboolean butt_down_mapcanvas(GtkWidget *w, GdkEventButton *ev, gpointer data)
Definition mapctrl.c:237
move_mapcanvas
gboolean move_mapcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:400
leave_mapcanvas
gboolean leave_mapcanvas(GtkWidget *widget, GdkEventCrossing *event)
Definition mapctrl.c:429
update_city_descriptions
void update_city_descriptions(void)
Definition mapview.c:470
map_canvas_draw
gboolean map_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data)
Definition mapview.c:407
map_canvas_configure
gboolean map_canvas_configure(GtkWidget *w, GdkEventConfigure *ev, gpointer data)
Definition mapview.c:386
put_unit_image
void put_unit_image(struct unit *punit, GtkImage *p, int height)
Definition mapview.c:478
overview_canvas_draw
gboolean overview_canvas_draw(GtkWidget *w, cairo_t *cr, gpointer data)
Definition mapview.c:339
setup_menus
GtkWidget * setup_menus(GtkWidget *window)
Definition menu.c:2115
menus_free
void menus_free(void)
Definition menu.c:3138
meswin_dialog_popup
void meswin_dialog_popup(bool raise)
Definition messagewin.c:416
create_start_page
GtkWidget * create_start_page(void)
Definition pages.c:2605
create_network_page
GtkWidget * create_network_page(void)
Definition pages.c:1183
create_scenario_page
GtkWidget * create_scenario_page(void)
Definition pages.c:3168
statusbar
static GtkWidget * statusbar
Definition pages.c:89
destroy_server_scans
void destroy_server_scans(void)
Definition pages.c:751
create_load_page
GtkWidget * create_load_page(void)
Definition pages.c:2886
create_statusbar
GtkWidget * create_statusbar(void)
Definition pages.c:892
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
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
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_level
log_level
Definition log.h:28
LOG_FATAL
@ LOG_FATAL
Definition log.h:29
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:662
maybe_activate_keyboardless_goto
void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
Definition mapctrl_common.c:504
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:549
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:3683
canvas_pos_to_tile
struct tile * canvas_pos_to_tile(float canvas_x, float canvas_y, float zoom)
Definition mapview_common.c:751
free_mapcanvas_and_overview
void free_mapcanvas_and_overview(void)
Definition mapview_common.c:3692
get_mapview_scroll_pos
void get_mapview_scroll_pos(int *scroll_x, int *scroll_y)
Definition mapview_common.c:1191
get_mapview_scroll_step
void get_mapview_scroll_step(int *xstep, int *ystep)
Definition mapview_common.c:1177
set_mapview_scroll_pos
void set_mapview_scroll_pos(int scroll_x, int scroll_y, float zoom)
Definition mapview_common.c:1200
center_tile_mapcanvas
void center_tile_mapcanvas(const struct tile *ptile)
Definition mapview_common.c:1222
set_frame_by_frame_animation
void set_frame_by_frame_animation(void)
Definition mapview_common.c:4081
link_marks_clear_all
void link_marks_clear_all(void)
Definition mapview_common.c:3952
mem.h
fc_malloc
#define fc_malloc(sz)
Definition mem.h:34
menus_init
void menus_init(void)
Definition update_queue.c:554
option_changed
void option_changed(struct option *poption)
Definition options.c:723
server_optset
const struct option_set * server_optset
Definition options.c:4009
client_optset
const struct option_set * client_optset
Definition options.c:1255
option_bool_get
bool option_bool_get(const struct option *poption)
Definition options.c:772
option_type
enum option_type option_type(const struct option *poption)
Definition options.c:633
option_font_target
const char * option_font_target(const struct option *poption)
Definition options.c:1138
string_to_video_mode
bool string_to_video_mode(const char *buf, struct video_mode *mode)
Definition options.c:6453
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:1116
optset_option_by_name
struct option * optset_option_by_name(const struct option_set *poptset, const char *name)
Definition options.c:406
options.h
GUI_GTK_OVERVIEW_MIN_XSIZE
#define GUI_GTK_OVERVIEW_MIN_XSIZE
Definition options.h:574
options_iterate
#define options_iterate(poptset, poption)
Definition options.h:527
GUI_GTK_MSGCHAT_MERGED
@ GUI_GTK_MSGCHAT_MERGED
Definition options.h:68
GUI_GTK_MSGCHAT_SPLIT
@ GUI_GTK_MSGCHAT_SPLIT
Definition options.h:66
options_iterate_end
#define options_iterate_end
Definition options.h:532
get_info_label_text_popup
const char * get_info_label_text_popup(void)
Definition text.c:1002
level
struct setting_list * level[OLEVELS_NUM]
Definition settings.c:183
CLIP
#define CLIP(lower, current, upper)
Definition shared.h:57
callback
Definition gui_main.c:2186
callback::data
void * data
Definition gui_main.c:2188
callback::callback
void(* callback)(void *data)
Definition gui_main.c:2187
civclient::conn
struct connection conn
Definition client_main.h:96
client_options::sound_effects_volume
int sound_effects_volume
Definition options.h:183
client_options::first_boot
bool first_boot
Definition options.h:124
client_options::migrate_fullscreen
bool migrate_fullscreen
Definition options.h:138
color
Definition colors.h:20
connection
Definition connection.h:141
connection::playing
struct player * playing
Definition connection.h:156
connection::notify_of_writable_data
void(* notify_of_writable_data)(struct connection *pc, bool data_available_and_socket_full)
Definition connection.h:186
connection::used
bool used
Definition connection.h:144
message
Definition messagewin_common.h:29
option
Definition options.c:454
sprite
Definition sprite.h:22
sprite::surface
cairo_surface_t * surface
Definition sprite.h:23
tileset
Definition tilespec.c:459
unit
Definition unit.h:138
unit::id
int id
Definition unit.h:145
video_mode
Definition options.h:45
video_mode::height
int height
Definition options.h:47
video_mode::width
int width
Definition options.h:46
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:969
cat_snprintf
int cat_snprintf(char *str, size_t n, const char *format,...)
Definition support.c:995
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:3452
tileset_free_tiles
void tileset_free_tiles(struct tileset *t)
Definition tilespec.c:6346
tileset_use_preferred_theme
void tileset_use_preferred_theme(const struct tileset *t)
Definition tilespec.c:6768
get_icon_sprite
struct sprite * get_icon_sprite(const struct tileset *t, enum icon_type icon)
Definition tilespec.c:6678
tileset_init
void tileset_init(struct tileset *t)
Definition tilespec.c:6827
get_arrow_sprite
struct sprite * get_arrow_sprite(const struct tileset *t, enum arrow_type arrow)
Definition tilespec.c:6568
get_tax_sprite
struct sprite * get_tax_sprite(const struct tileset *t, Output_type_id otype)
Definition tilespec.c:6579
tileset_tile_width
int tileset_tile_width(const struct tileset *t)
Definition tilespec.c:716
tilespec.h
ARROW_RIGHT
@ ARROW_RIGHT
Definition tilespec.h:199
ICON_FREECIV
@ ICON_FREECIV
Definition tilespec.h:310
unit_tile
#define unit_tile(_pu)
Definition unit.h:388
unit_owner
#define unit_owner(_pu)
Definition unit.h:387
unitlist.h
version.h
enable
#define enable(id)
Definition widget.h:223
mouse_zoom
float mouse_zoom
Definition zoom.c:28
zoom_step_down
void zoom_step_down(void)
Definition zoom.c:130
zoom_step_up
void zoom_step_up(void)
Definition zoom.c:106
zoom.h