Freeciv-3.1
Loading...
Searching...
No Matches
mapctrl.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#include <gtk/gtk.h>
19
20/* utility */
21#include "fcintl.h"
22#include "support.h"
23
24/* common */
25#include "combat.h"
26#include "game.h"
27#include "map.h"
28#include "player.h"
29#include "unit.h"
30
31#include "overview_common.h"
32
33/* client */
34#include "client_main.h"
35#include "climap.h"
36#include "climisc.h"
37#include "control.h"
38#include "editor.h"
39#include "tilespec.h"
40#include "text.h"
41#include "zoom.h"
42
43/* client/agents */
44#include "cma_core.h"
45
46/* client/gui-gtk-4.0 */
47#include "chatline.h"
48#include "citydlg.h"
49#include "colors.h"
50#include "dialogs.h"
51#include "editgui.h"
52#include "graphics.h"
53#include "gui_main.h"
54#include "infradlg.h"
55#include "inputdlg.h"
56#include "mapview.h"
57#include "menu.h"
58#include "rallypointdlg.h"
59
60#include "mapctrl.h"
61
62extern gint cur_x, cur_y;
63
64/**********************************************************************/
68static void popit(struct tile *ptile)
69{
70 if (TILE_UNKNOWN != client_tile_get_known(ptile)) {
71 GtkWidget *p;
72 struct unit *punit;
73 GdkRectangle rect;
74 GtkAllocation alloc;
75 float canvas_x, canvas_y;
76
78 gtk_widget_get_allocation(map_canvas, &alloc);
79 rect.x = (canvas_x * mouse_zoom / map_zoom) - alloc.x;
80 rect.y = (canvas_y * mouse_zoom / map_zoom) - alloc.y;
81 rect.width = tileset_full_tile_width(tileset);
82 rect.height = tileset_tile_height(tileset);
83
84 p = gtk_popover_new();
85
86 gtk_widget_set_parent(p, map_canvas);
87 gtk_popover_set_pointing_to(GTK_POPOVER(p), &rect);
88 gtk_popover_set_child(GTK_POPOVER(p), gtk_label_new(popup_info_text(ptile)));
89
90 punit = find_visible_unit(ptile);
91
92 if (punit) {
94 if (punit->goto_tile) {
96 }
97 }
99
100 g_signal_connect(p, "closed",
101 G_CALLBACK(popupinfo_popdown_callback), NULL);
102
103 gtk_popover_popup(GTK_POPOVER(p));
104 }
105}
106
107/**********************************************************************/
110void popupinfo_popdown_callback(GtkWidget *w, gpointer data)
111{
114}
115
116/**********************************************************************/
119static void name_new_city_popup_callback(gpointer data, gint response,
120 const char *input)
121{
122 int idx = GPOINTER_TO_INT(data);
123
124 switch (response) {
125 case GTK_RESPONSE_OK:
126 finish_city(index_to_tile(&(wld.map), idx), input);
127 break;
128 case GTK_RESPONSE_CANCEL:
129 case GTK_RESPONSE_DELETE_EVENT:
131 break;
132 }
133}
134
135/**********************************************************************/
140void popup_newcity_dialog(struct unit *punit, const char *suggestname)
141{
142 input_dialog_create(GTK_WINDOW(toplevel), /*"shellnewcityname" */
143 _("Build New City"),
144 _("What should we call our new city?"), suggestname,
146 GINT_TO_POINTER(tile_index(unit_tile(punit))));
147}
148
149/**********************************************************************/
154{
155 gtk_widget_set_sensitive(turn_done_button, state);
156
158}
159
160/**********************************************************************/
164gboolean left_butt_up_mapcanvas(GtkGestureClick *gesture, int n_press,
165 double x, double y, gpointer data)
166{
167 if (editor_is_active()) {
169 x, y);
170 }
171
173
174 return TRUE;
175}
176
177/**********************************************************************/
181gboolean right_butt_up_mapcanvas(GtkGestureClick *gesture, int n_press,
182 double x, double y, gpointer data)
183{
184 if (editor_is_active()) {
186 x, y);
187 }
188
190
192 GdkModifierType state;
193
194 state = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
196 (state & GDK_SHIFT_MASK) != 0);
197 }
198
199 return TRUE;
200}
201
202/**********************************************************************/
206gboolean left_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press,
207 double x, double y, gpointer data)
208{
209 struct tile *ptile = NULL;
210 GdkModifierType state;
211
212 if (editor_is_active()) {
214 x, y);
215 }
216
217 if (!can_client_change_view()) {
218 return TRUE;
219 }
220
221 gtk_widget_grab_focus(map_canvas);
222 ptile = canvas_pos_to_tile(x, y, mouse_zoom);
223
224 state = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
225
226 /* <SHIFT> + <CONTROL> + LMB : Adjust workers. */
227 if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK)) {
229 } else if (state & GDK_CONTROL_MASK) {
230 /* <CONTROL> + LMB : Quickselect a sea unit. */
232 } else if (ptile && (state & GDK_SHIFT_MASK)) {
233 /* <SHIFT> + LMB: Append focus unit. */
235 } else if (ptile && (state & GDK_ALT_MASK)) {
236 /* <ALT> + LMB: popit (same as middle-click) */
237 /* FIXME: we need a general mechanism for letting freeciv work with
238 * 1- or 2-button mice. */
239 popit(ptile);
240 } else if (tiles_hilited_cities) {
241 /* LMB in Area Selection mode. */
242 if (ptile) {
243 toggle_tile_hilite(ptile);
244 }
245 } else if (rally_set_tile(ptile)) {
246 /* Nothing here, rally_set_tile() already did what we wanted */
247 } else if (infra_placement_mode()) {
249 } else {
250 /* Plain LMB click. */
252 }
253
254 return TRUE;
255}
256
257/**********************************************************************/
261gboolean right_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press,
262 double x, double y, gpointer data)
263{
264 struct city *pcity = NULL;
265 struct tile *ptile = NULL;
266 GdkModifierType state;
267
268 if (editor_is_active()) {
270 x, y);
271 }
272
273 if (!can_client_change_view()) {
274 return TRUE;
275 }
276
277 gtk_widget_grab_focus(map_canvas);
278 ptile = canvas_pos_to_tile(x, y, mouse_zoom);
279 pcity = ptile ? tile_city(ptile) : NULL;
280
281 state = gtk_event_controller_get_current_event_state(
282 GTK_EVENT_CONTROLLER(gesture));
283
284 /* <CONTROL> + <ALT> + RMB : insert city or tile chat link. */
285 /* <CONTROL> + <ALT> + <SHIFT> + RMB : insert unit chat link. */
286 if (ptile && (state & GDK_ALT_MASK)
287 && (state & GDK_CONTROL_MASK)) {
288 inputline_make_chat_link(ptile, (state & GDK_SHIFT_MASK) != 0);
289 } else if ((state & GDK_SHIFT_MASK) && (state & GDK_ALT_MASK)) {
290 /* <SHIFT> + <ALT> + RMB : Show/hide workers. */
291 key_city_overlay(x, y);
292 } else if ((state & GDK_SHIFT_MASK) && (state & GDK_CONTROL_MASK)
293 && pcity != NULL) {
294 /* <SHIFT + CONTROL> + RMB: Paste Production. */
297 } else if (state & GDK_SHIFT_MASK
298 && clipboard_copy_production(ptile)) {
299 /* <SHIFT> + RMB on city/unit: Copy Production. */
300 /* If nothing to copy, fall through to rectangle selection. */
301
302 /* Already done the copy */
303 } else if (state & GDK_CONTROL_MASK) {
304 /* <CONTROL> + RMB : Quickselect a land unit. */
306 } else {
307 /* Plain RMB click. Area selection. */
308 /* A foolproof user will depress button on canvas,
309 * release it on another widget, and return to canvas
310 * to find rectangle still active.
311 */
312 if (rectangle_active) {
314 (state & GDK_SHIFT_MASK) != 0);
315 return TRUE;
316 }
317 if (hover_state == HOVER_NONE) {
319 rbutton_down = TRUE; /* Causes rectangle updates */
320 }
321 }
322
323 return TRUE;
324}
325
326/**********************************************************************/
330gboolean middle_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press,
331 double x, double y, gpointer data)
332{
333 struct tile *ptile = NULL;
334 GdkModifierType state;
335
336 if (editor_is_active()) {
338 x, y);
339 }
340
341 if (!can_client_change_view()) {
342 return TRUE;
343 }
344
345 gtk_widget_grab_focus(map_canvas);
346 ptile = canvas_pos_to_tile(x, y, mouse_zoom);
347
348 state = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
349
350 /* <CONTROL> + MMB: Wake up sentries. */
351 if (state & GDK_CONTROL_MASK) {
353 } else if (ptile) {
354 /* Plain Middle click. */
355 popit(ptile);
356 }
357
358 return TRUE;
359}
360
361/**********************************************************************/
365{
366 double x, y;
367 GdkSeat *seat = gdk_display_get_default_seat(gtk_widget_get_display(toplevel));
368 GdkDevice *pointer = gdk_seat_get_pointer(seat);
369 GdkSurface *window;
370
371 if (!pointer) {
372 return;
373 }
374
375 window = gdk_device_get_surface_at_position(pointer, &x, &y);
376 if (window) {
377 if (window == gtk_native_get_surface(gtk_widget_get_native(map_canvas))) {
378 update_line(x, y);
379 } else if (window == gtk_native_get_surface(gtk_widget_get_native(overview_canvas))) {
381 }
382 }
383}
384
385/**********************************************************************/
390{
391 double x, y;
392 GdkSurface *window;
393 GdkDevice *pointer;
394 GdkDevice *keyboard;
395 GdkModifierType mask;
396 GdkSeat *seat = gdk_display_get_default_seat(gtk_widget_get_display(toplevel));
397
398 pointer = gdk_seat_get_pointer(seat);
399 if (!pointer) {
400 return;
401 }
402
403 window = gdk_device_get_surface_at_position(pointer, &x, &y);
404 if (window
405 && window == gtk_native_get_surface(gtk_widget_get_native(map_canvas))) {
406 keyboard = gdk_seat_get_keyboard(seat);
407 mask = gdk_device_get_modifier_state(keyboard);
408 if (mask & GDK_BUTTON3_MASK) {
410 }
411 }
412}
413
414/**********************************************************************/
418gboolean move_mapcanvas(GtkEventControllerMotion *controller,
419 gdouble x, gdouble y, gpointer data)
420{
421 GdkModifierType state;
422
423 if (GUI_GTK_OPTION(mouse_over_map_focus)
424 && !gtk_widget_has_focus(map_canvas)) {
425 gtk_widget_grab_focus(map_canvas);
426 }
427
428 if (editor_is_active()) {
429 return handle_edit_mouse_move(controller, x, y);
430 }
431
432 cur_x = x;
433 cur_y = y;
434 update_line(x, y);
435 state = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(controller));
436 if (rbutton_down && (state & GDK_BUTTON3_MASK)) {
438 }
439
442 }
444
445 return TRUE;
446}
447
448/**********************************************************************/
451gboolean leave_mapcanvas(GtkEventControllerMotion *controller,
452 gpointer data)
453{
456
457 return TRUE;
458}
459
460/**********************************************************************/
463gboolean move_overviewcanvas(GtkEventControllerMotion *controller,
464 gdouble x, gdouble y, gpointer data)
465{
467
468 return TRUE;
469}
470
471/**********************************************************************/
474gboolean left_butt_down_overviewcanvas(GtkGestureClick *gesture, int n_press,
475 double x, double y, gpointer data)
476{
477 int xtile, ytile;
478
479 if (n_press != 1) {
480 return TRUE; /* Double-clicks? Triple-clicks? No thanks! */
481 }
482
483 overview_to_map_pos(&xtile, &ytile, x, y);
484
486 GdkModifierType state;
487
488 state = gtk_event_controller_get_current_event_state(GTK_EVENT_CONTROLLER(gesture));
489 do_map_click(map_pos_to_tile(&(wld.map), xtile, ytile),
490 (state & GDK_SHIFT_MASK) ? SELECT_APPEND : SELECT_POPUP);
491 }
492
493 return TRUE;
494}
495
496/**********************************************************************/
499gboolean right_butt_down_overviewcanvas(GtkGestureClick *gesture, int n_press,
500 double x, double y, gpointer data)
501{
502 int xtile, ytile;
503
504 if (n_press != 1) {
505 return TRUE; /* Double-clicks? Triple-clicks? No thanks! */
506 }
507
508 overview_to_map_pos(&xtile, &ytile, x, y);
509
511 center_tile_mapcanvas(map_pos_to_tile(&(wld.map), xtile, ytile));
512 }
513
514 return TRUE;
515}
516
517/**********************************************************************/
521{
523}
struct canvas int int canvas_y
Definition canvas_g.h:43
struct canvas int canvas_x
Definition canvas_g.h:43
bool can_client_issue_orders(void)
bool can_client_change_view(void)
enum known_type client_tile_get_known(const struct tile *ptile)
Definition climap.c:36
void do_map_click(struct tile *ptile, enum quickselect_type qtype)
Definition control.c:2795
struct unit_list * get_units_in_focus(void)
Definition control.c:177
void request_center_focus_unit(void)
Definition control.c:2637
enum cursor_hover_state hover_state
Definition control.c:89
void finish_city(struct tile *ptile, const char *name)
Definition control.c:3969
struct unit * find_visible_unit(struct tile *ptile)
Definition control.c:823
void control_mouse_cursor(struct tile *ptile)
Definition control.c:1214
void cancel_city(struct tile *ptile)
Definition control.c:3988
@ SELECT_LAND
Definition control.h:37
@ SELECT_APPEND
Definition control.h:37
@ SELECT_SEA
Definition control.h:37
@ SELECT_POPUP
Definition control.h:37
@ HOVER_NONE
Definition control.h:26
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
bool editor_is_active(void)
Definition editor.c:346
@ MOUSE_BUTTON_LEFT
Definition editor.h:126
@ MOUSE_BUTTON_RIGHT
Definition editor.h:128
@ MOUSE_BUTTON_MIDDLE
Definition editor.h:127
#define _(String)
Definition fcintl.h:67
struct world wld
Definition game.c:58
void inputline_make_chat_link(struct tile *ptile, bool unit)
Definition chatline.c:474
gboolean handle_edit_mouse_button_release(GdkEventButton *ev)
Definition editgui.c:955
gboolean handle_edit_mouse_button_press(GdkEventButton *ev)
Definition editgui.c:939
gboolean handle_edit_mouse_move(GdkEventMotion *ev)
Definition editgui.c:970
GtkWidget * turn_done_button
Definition gui_main.c:148
GtkWidget * overview_canvas
Definition gui_main.c:110
GtkWidget * toplevel
Definition gui_main.c:124
GtkWidget * map_canvas
Definition gui_main.c:106
void update_turn_done_tooltip(void)
Definition gui_main.c:1055
#define GUI_GTK_OPTION(optname)
Definition gui_main.h:25
GtkWidget * input_dialog_create(GtkWindow *parent, const char *dialogname, const char *text, const char *postinputtest, input_dialog_callback_t response_callback, gpointer response_cli_data)
Definition inputdlg.c:66
gboolean move_overviewcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:458
gint cur_y
Definition mapctrl.c:61
void popup_newcity_dialog(struct unit *punit, const char *suggestname)
Definition mapctrl.c:194
void center_on_unit(void)
Definition mapctrl.c:490
void create_line_at_mouse_pos(void)
Definition mapctrl.c:347
gboolean move_mapcanvas(GtkWidget *w, GdkEventMotion *ev, gpointer data)
Definition mapctrl.c:400
gint cur_x
Definition gui_main.c:183
void set_turn_done_button_state(bool state)
Definition mapctrl.c:207
gboolean leave_mapcanvas(GtkWidget *widget, GdkEventCrossing *event)
Definition mapctrl.c:429
static void popit(GdkEventButton *event, struct tile *ptile)
Definition mapctrl.c:118
void popupinfo_popdown_callback(GtkWidget *w, gpointer data)
Definition mapctrl.c:164
static void name_new_city_popup_callback(gpointer data, gint response, const char *input)
Definition mapctrl.c:173
void update_rect_at_mouse_pos(void)
Definition mapctrl.c:373
void update_unit_info_label(struct unit_list *punits)
Definition mapview.c:258
void update_mouse_cursor(enum cursor_type new_cursor_type)
Definition mapview.c:240
bool infra_placement_mode(void)
Definition infradlg.c:155
void infra_placement_set_tile(struct tile *ptile)
Definition infradlg.c:163
bool rally_set_tile(struct tile *ptile)
gboolean right_butt_down_overviewcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:499
gboolean left_butt_up_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:164
gboolean right_butt_up_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:181
gboolean left_butt_down_overviewcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:474
gboolean left_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:206
gboolean right_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:261
gboolean middle_butt_down_mapcanvas(GtkGestureClick *gesture, int n_press, double x, double y, gpointer data)
Definition mapctrl.c:330
struct tile * index_to_tile(const struct civ_map *imap, int mindex)
Definition map.c:454
struct tile * map_pos_to_tile(const struct civ_map *nmap, int map_x, int map_y)
Definition map.c:417
void update_line(int canvas_x, int canvas_y)
void maybe_activate_keyboardless_goto(int canvas_x, int canvas_y)
void adjust_workers_button_pressed(int canvas_x, int canvas_y)
bool rbutton_down
bool rectangle_active
void release_goto_button(int canvas_x, int canvas_y)
bool tiles_hilited_cities
void action_button_pressed(int canvas_x, int canvas_y, enum quickselect_type qtype)
void wakeup_button_pressed(int canvas_x, int canvas_y)
void release_right_button(int canvas_x, int canvas_y, bool shift)
bool keyboardless_goto_button_down
void key_city_overlay(int canvas_x, int canvas_y)
void update_selection_rectangle(float canvas_x, float canvas_y)
void overview_update_line(int overview_x, int overview_y)
void anchor_selection_rectangle(int canvas_x, int canvas_y)
void cancel_tile_hiliting(void)
void clipboard_paste_production(struct city *pcity)
bool clipboard_copy_production(struct tile *ptile)
void toggle_tile_hilite(struct tile *ptile)
void mapdeco_set_crosshair(const struct tile *ptile, bool crosshair)
struct tile * canvas_pos_to_tile(float canvas_x, float canvas_y, float zoom)
void mapdeco_set_gotoroute(const struct unit *punit)
void mapdeco_clear_gotoroutes(void)
void center_tile_mapcanvas(const struct tile *ptile)
void mapdeco_clear_crosshairs(void)
bool tile_to_canvas_pos(float *canvas_x, float *canvas_y, float zoom, const struct tile *ptile)
void overview_to_map_pos(int *map_x, int *map_y, int overview_x, int overview_y)
Definition city.h:309
Definition tile.h:49
Definition unit.h:138
struct tile * goto_tile
Definition unit.h:155
struct civ_map map
#define TRUE
Definition support.h:46
const char * popup_info_text(struct tile *ptile)
Definition text.c:146
struct city * tile_city(const struct tile *ptile)
Definition tile.c:83
#define tile_index(_pt_)
Definition tile.h:87
@ TILE_UNKNOWN
Definition tile.h:35
int tileset_tile_height(const struct tileset *t)
Definition tilespec.c:728
int tileset_full_tile_width(const struct tileset *t)
Definition tilespec.c:739
@ CURSOR_DEFAULT
Definition tilespec.h:297
#define unit_tile(_pu)
Definition unit.h:395
float mouse_zoom
Definition zoom.c:28
float map_zoom
Definition zoom.c:25