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 "widgets/gimpdeviceinfo.h"
26 #include "widgets/gimpdeviceinfo-coords.h"
27
28 #include "gimpdisplay.h"
29 #include "gimpdisplayshell.h"
30 #include "gimpdisplayshell-autoscroll.h"
31 #include "gimpdisplayshell-scroll.h"
32 #include "gimpdisplayshell-transform.h"
33
34 #include "tools/tools-types.h"
35 #include "tools/tool_manager.h"
36 #include "tools/gimptool.h"
37 #include "tools/gimptoolcontrol.h"
38
39
40 #define AUTOSCROLL_DT 20
41 #define AUTOSCROLL_DX 0.1
42
43
44 typedef struct
45 {
46 GdkEventMotion *mevent;
47 GimpDeviceInfo *device;
48 guint32 time;
49 GdkModifierType state;
50 guint timeout_id;
51 } ScrollInfo;
52
53
54 /* local function prototypes */
55
56 static gboolean gimp_display_shell_autoscroll_timeout (gpointer data);
57
58
59 /* public functions */
60
61 void
gimp_display_shell_autoscroll_start(GimpDisplayShell * shell,GdkModifierType state,GdkEventMotion * mevent)62 gimp_display_shell_autoscroll_start (GimpDisplayShell *shell,
63 GdkModifierType state,
64 GdkEventMotion *mevent)
65 {
66 ScrollInfo *info;
67
68 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
69
70 if (shell->scroll_info)
71 return;
72
73 info = g_slice_new0 (ScrollInfo);
74
75 info->mevent = mevent;
76 info->device = gimp_device_info_get_by_device (mevent->device);
77 info->time = gdk_event_get_time ((GdkEvent *) mevent);
78 info->state = state;
79 info->timeout_id = g_timeout_add (AUTOSCROLL_DT,
80 gimp_display_shell_autoscroll_timeout,
81 shell);
82
83 shell->scroll_info = info;
84 }
85
86 void
gimp_display_shell_autoscroll_stop(GimpDisplayShell * shell)87 gimp_display_shell_autoscroll_stop (GimpDisplayShell *shell)
88 {
89 ScrollInfo *info;
90
91 g_return_if_fail (GIMP_IS_DISPLAY_SHELL (shell));
92
93 if (! shell->scroll_info)
94 return;
95
96 info = shell->scroll_info;
97
98 if (info->timeout_id)
99 {
100 g_source_remove (info->timeout_id);
101 info->timeout_id = 0;
102 }
103
104 g_slice_free (ScrollInfo, info);
105 shell->scroll_info = NULL;
106 }
107
108
109 /* private functions */
110
111 static gboolean
gimp_display_shell_autoscroll_timeout(gpointer data)112 gimp_display_shell_autoscroll_timeout (gpointer data)
113 {
114 GimpDisplayShell *shell = GIMP_DISPLAY_SHELL (data);
115 ScrollInfo *info = shell->scroll_info;
116 GimpCoords device_coords;
117 GimpCoords image_coords;
118 gint dx = 0;
119 gint dy = 0;
120
121 gimp_device_info_get_device_coords (info->device,
122 gtk_widget_get_window (shell->canvas),
123 &device_coords);
124
125 if (device_coords.x < 0)
126 dx = device_coords.x;
127 else if (device_coords.x > shell->disp_width)
128 dx = device_coords.x - shell->disp_width;
129
130 if (device_coords.y < 0)
131 dy = device_coords.y;
132 else if (device_coords.y > shell->disp_height)
133 dy = device_coords.y - shell->disp_height;
134
135 if (dx || dy)
136 {
137 GimpDisplay *display = shell->display;
138 GimpTool *active_tool = tool_manager_get_active (display->gimp);
139 gint scroll_amount_x = AUTOSCROLL_DX * dx;
140 gint scroll_amount_y = AUTOSCROLL_DX * dy;
141
142 info->time += AUTOSCROLL_DT;
143
144 gimp_display_shell_scroll_unoverscrollify (shell,
145 scroll_amount_x,
146 scroll_amount_y,
147 &scroll_amount_x,
148 &scroll_amount_y);
149
150 gimp_display_shell_scroll (shell,
151 scroll_amount_x,
152 scroll_amount_y);
153
154 gimp_display_shell_untransform_coords (shell,
155 &device_coords,
156 &image_coords);
157
158 if (gimp_tool_control_get_snap_to (active_tool->control))
159 {
160 gint x, y, width, height;
161
162 gimp_tool_control_get_snap_offsets (active_tool->control,
163 &x, &y, &width, &height);
164
165 gimp_display_shell_snap_coords (shell,
166 &image_coords,
167 x, y, width, height);
168 }
169
170 tool_manager_motion_active (display->gimp,
171 &image_coords,
172 info->time, info->state,
173 display);
174
175 return TRUE;
176 }
177 else
178 {
179 g_slice_free (ScrollInfo, info);
180 shell->scroll_info = NULL;
181
182 return FALSE;
183 }
184 }
185