1 /* GIMP - The GNU Image Manipulation Program
2 * Copyright (C) 1995 Spencer Kimball and Peter Mattis
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <https://www.gnu.org/licenses/>.
16 */
17
18 #include "config.h"
19
20 #include <gegl.h>
21 #include <gtk/gtk.h>
22
23 #include "display-types.h"
24
25 #include "config/gimpguiconfig.h"
26
27 #include "core/gimpimage.h"
28
29 #include "widgets/gimpcursor.h"
30 #include "widgets/gimpdialogfactory.h"
31 #include "widgets/gimpdockcontainer.h"
32 #include "widgets/gimpsessioninfo.h"
33
34 #include "gimpcanvascursor.h"
35 #include "gimpdisplay.h"
36 #include "gimpcursorview.h"
37 #include "gimpdisplayshell.h"
38 #include "gimpdisplayshell-cursor.h"
39 #include "gimpdisplayshell-transform.h"
40 #include "gimpstatusbar.h"
41
42
43 static void gimp_display_shell_real_set_cursor (GimpDisplayShell *shell,
44 GimpCursorType cursor_type,
45 GimpToolCursorType tool_cursor,
46 GimpCursorModifier modifier,
47 gboolean always_install);
48
49
50 /* public functions */
51
52 void
gimp_display_shell_set_cursor(GimpDisplayShell * shell,GimpCursorType cursor_type,GimpToolCursorType tool_cursor,GimpCursorModifier modifier)53 gimp_display_shell_set_cursor (GimpDisplayShell *shell,
54 GimpCursorType cursor_type,
55 GimpToolCursorType tool_cursor,
56 GimpCursorModifier modifier)
57 {
58 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
59
60 if (! shell->using_override_cursor)
61 {
62 gimp_display_shell_real_set_cursor (shell,
63 cursor_type,
64 tool_cursor,
65 modifier,
66 FALSE);
67 }
68 }
69
70 void
gimp_display_shell_unset_cursor(GimpDisplayShell * shell)71 gimp_display_shell_unset_cursor (GimpDisplayShell *shell)
72 {
73 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
74
75 if (! shell->using_override_cursor)
76 {
77 gimp_display_shell_real_set_cursor (shell,
78 (GimpCursorType) -1, 0, 0, FALSE);
79 }
80 }
81
82 void
gimp_display_shell_set_override_cursor(GimpDisplayShell * shell,GimpCursorType cursor_type)83 gimp_display_shell_set_override_cursor (GimpDisplayShell *shell,
84 GimpCursorType cursor_type)
85 {
86 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
87
88 if (! shell->using_override_cursor ||
89 (shell->using_override_cursor &&
90 shell->override_cursor != cursor_type))
91 {
92 shell->override_cursor = cursor_type;
93 shell->using_override_cursor = TRUE;
94
95 gimp_cursor_set (shell->canvas,
96 shell->cursor_handedness,
97 cursor_type,
98 GIMP_TOOL_CURSOR_NONE,
99 GIMP_CURSOR_MODIFIER_NONE);
100 }
101 }
102
103 void
gimp_display_shell_unset_override_cursor(GimpDisplayShell * shell)104 gimp_display_shell_unset_override_cursor (GimpDisplayShell *shell)
105 {
106 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
107
108 if (shell->using_override_cursor)
109 {
110 shell->using_override_cursor = FALSE;
111
112 gimp_display_shell_real_set_cursor (shell,
113 shell->current_cursor,
114 shell->tool_cursor,
115 shell->cursor_modifier,
116 TRUE);
117 }
118 }
119
120 void
gimp_display_shell_update_software_cursor(GimpDisplayShell * shell,GimpCursorPrecision precision,gint display_x,gint display_y,gdouble image_x,gdouble image_y)121 gimp_display_shell_update_software_cursor (GimpDisplayShell *shell,
122 GimpCursorPrecision precision,
123 gint display_x,
124 gint display_y,
125 gdouble image_x,
126 gdouble image_y)
127 {
128 GimpImageWindow *image_window;
129 GimpDialogFactory *factory;
130 GimpStatusbar *statusbar;
131 GtkWidget *widget;
132 GimpImage *image;
133
134 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
135
136 image = gimp_display_get_image (shell->display);
137
138 if (shell->draw_cursor &&
139 shell->proximity &&
140 display_x >= 0 &&
141 display_y >= 0)
142 {
143 gimp_canvas_item_begin_change (shell->cursor);
144
145 gimp_canvas_cursor_set (shell->cursor,
146 display_x,
147 display_y);
148 gimp_canvas_item_set_visible (shell->cursor, TRUE);
149
150 gimp_canvas_item_end_change (shell->cursor);
151 }
152 else
153 {
154 gimp_canvas_item_set_visible (shell->cursor, FALSE);
155 }
156
157 /* use the passed image_coords for the statusbar because they are
158 * possibly snapped...
159 */
160 statusbar = gimp_display_shell_get_statusbar (shell);
161
162 gimp_statusbar_update_cursor (statusbar, precision, image_x, image_y);
163
164 image_window = gimp_display_shell_get_window (shell);
165 factory = gimp_dock_container_get_dialog_factory (GIMP_DOCK_CONTAINER (image_window));
166
167 widget = gimp_dialog_factory_find_widget (factory, "gimp-cursor-view");
168
169 if (widget)
170 {
171 GtkWidget *cursor_view = gtk_bin_get_child (GTK_BIN (widget));
172
173 if (cursor_view)
174 {
175 gint t_x = -1;
176 gint t_y = -1;
177
178 /* ...but use the unsnapped display_coords for the info window */
179 if (display_x >= 0 && display_y >= 0)
180 gimp_display_shell_untransform_xy (shell, display_x, display_y,
181 &t_x, &t_y, FALSE);
182
183 gimp_cursor_view_update_cursor (GIMP_CURSOR_VIEW (cursor_view),
184 image, shell->unit,
185 t_x, t_y);
186 }
187 }
188 }
189
190 void
gimp_display_shell_clear_software_cursor(GimpDisplayShell * shell)191 gimp_display_shell_clear_software_cursor (GimpDisplayShell *shell)
192 {
193 GimpImageWindow *image_window;
194 GimpDialogFactory *factory;
195 GimpStatusbar *statusbar;
196 GtkWidget *widget;
197
198 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
199
200 gimp_canvas_item_set_visible (shell->cursor, FALSE);
201
202 statusbar = gimp_display_shell_get_statusbar (shell);
203
204 gimp_statusbar_clear_cursor (statusbar);
205
206 image_window = gimp_display_shell_get_window (shell);
207 factory = gimp_dock_container_get_dialog_factory (GIMP_DOCK_CONTAINER (image_window));
208
209 widget = gimp_dialog_factory_find_widget (factory, "gimp-cursor-view");
210
211 if (widget)
212 {
213 GtkWidget *cursor_view = gtk_bin_get_child (GTK_BIN (widget));
214
215 if (cursor_view)
216 gimp_cursor_view_clear_cursor (GIMP_CURSOR_VIEW (cursor_view));
217 }
218 }
219
220
221 /* private functions */
222
223 static void
gimp_display_shell_real_set_cursor(GimpDisplayShell * shell,GimpCursorType cursor_type,GimpToolCursorType tool_cursor,GimpCursorModifier modifier,gboolean always_install)224 gimp_display_shell_real_set_cursor (GimpDisplayShell *shell,
225 GimpCursorType cursor_type,
226 GimpToolCursorType tool_cursor,
227 GimpCursorModifier modifier,
228 gboolean always_install)
229 {
230 GimpHandedness cursor_handedness;
231
232 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
233
234 if (cursor_type == (GimpCursorType) -1)
235 {
236 shell->current_cursor = cursor_type;
237
238 if (gtk_widget_is_drawable (shell->canvas))
239 gdk_window_set_cursor (gtk_widget_get_window (shell->canvas), NULL);
240
241 return;
242 }
243
244 if (cursor_type != GIMP_CURSOR_NONE &&
245 cursor_type != GIMP_CURSOR_BAD)
246 {
247 switch (shell->display->config->cursor_mode)
248 {
249 case GIMP_CURSOR_MODE_TOOL_ICON:
250 break;
251
252 case GIMP_CURSOR_MODE_TOOL_CROSSHAIR:
253 if (cursor_type < GIMP_CURSOR_CORNER_TOP ||
254 cursor_type > GIMP_CURSOR_SIDE_TOP_LEFT)
255 {
256 /* the corner and side cursors count as crosshair, so leave
257 * them and override everything else
258 */
259 cursor_type = GIMP_CURSOR_CROSSHAIR_SMALL;
260 }
261 break;
262
263 case GIMP_CURSOR_MODE_CROSSHAIR:
264 cursor_type = GIMP_CURSOR_CROSSHAIR;
265 tool_cursor = GIMP_TOOL_CURSOR_NONE;
266
267 if (modifier != GIMP_CURSOR_MODIFIER_BAD)
268 {
269 /* the bad modifier is always shown */
270 modifier = GIMP_CURSOR_MODIFIER_NONE;
271 }
272 break;
273 }
274 }
275
276 cursor_type = gimp_cursor_rotate (cursor_type, shell->rotate_angle);
277
278 cursor_handedness = GIMP_GUI_CONFIG (shell->display->config)->cursor_handedness;
279
280 if (shell->cursor_handedness != cursor_handedness ||
281 shell->current_cursor != cursor_type ||
282 shell->tool_cursor != tool_cursor ||
283 shell->cursor_modifier != modifier ||
284 always_install)
285 {
286 shell->cursor_handedness = cursor_handedness;
287 shell->current_cursor = cursor_type;
288 shell->tool_cursor = tool_cursor;
289 shell->cursor_modifier = modifier;
290
291 gimp_cursor_set (shell->canvas,
292 cursor_handedness,
293 cursor_type, tool_cursor, modifier);
294 }
295 }
296