/
main.c
162 lines (124 loc) · 3.9 KB
/
main.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
#include "app.h"
#include "callbacks.h"
const gint Sensitivity = 10;
int offsetx, offsety, px, py, maxx, maxy;
inline static int
Min (const int a, const int b)
{
return b < a ? b : a;
}
inline static int
Max (const int a, const int b)
{
return b > a ? b : a;
}
inline static int
RoundDownToMultiple (const int i, const int m)
{
return i / m * m;
}
inline static int
RoundToNearestMultiple (const int i, const int m)
{
if (i % m > (double) m / 2.0)
return (i / m + 1) * m;
return i / m * m;
}
static void
destroy (GtkWidget * widget, gpointer data)
{
gtk_main_quit ();
}
static gboolean
button_press_event (GtkWidget * w, GdkEventButton * event,
App * app)
{
if (event->button == 1) {
GtkAllocation alloc_w, alloc_p;
GtkWidget *p;
p = gtk_widget_get_parent (w);
gtk_widget_get_allocation (w, &alloc_w);
gtk_widget_get_allocation (p, &alloc_p);
// offset == distance of parent widget from edge of screen ...
// plus distance from pointer to edge of widget
offsetx = (int) event->x;
offsety = (int) event->y;
// maxx, maxy both relative to the parent
// note that we're rounding down now so that these max values don't get
// rounded upward later and push the widget off the edge of its parent.
maxx =
RoundDownToMultiple (alloc_p.width -
alloc_w.width, Sensitivity);
maxy =
RoundDownToMultiple (alloc_p.height -
alloc_w.height, Sensitivity);
}
return TRUE;
}
static gboolean
motion_notify_event (GtkWidget * widget,
GdkEventMotion * event, App * app)
{
gint x, y;
gboolean ret;
GtkAdjustment *hadjustment, *vadjustment;
gfloat hval, vval;
GET_UI_ELEMENT (GtkWidget, scrolledwindow2);
GET_UI_ELEMENT (GtkWidget, layout1);
gtk_widget_translate_coordinates (widget, layout1,
event->x, event->y, &x,
&y);
x -= offsetx;
y -= offsety;
// make sure the potential coordinates x,y:
// 1) will not push any part of the widget outside of its parent container
// 2) is a multiple of Sensitivity
x = RoundToNearestMultiple (Max (Min (x, maxx), 0),
Sensitivity);
y = RoundToNearestMultiple (Max (Min (y, maxy), 0),
Sensitivity);
if (x != px || y != py) {
g_object_get (scrolledwindow2, "hadjustment",
&hadjustment, "vadjustment",
&vadjustment, NULL);
hval = gtk_adjustment_get_value (hadjustment);
vval = gtk_adjustment_get_value (vadjustment);
x += hval;
y += vval;
px = x;
py = y;
gtk_layout_move (GTK_LAYOUT (layout1), widget, x, y);
}
gtk_widget_queue_draw (layout1);
return TRUE;
}
void
make_button (const gchar * const name, App * app)
{
GtkWidget *b =
(GtkWidget *) app_get_ui_element (app, name);
gtk_widget_add_events (b,
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON1_MOTION_MASK);
g_signal_connect (G_OBJECT (b), "button-press-event",
G_CALLBACK (button_press_event), app);
g_signal_connect (G_OBJECT (b), "motion-notify-event",
G_CALLBACK (motion_notify_event), app);
}
int
main (int argc, char *argv[])
{
App *app;
app = (App *) g_new (App, 1);
gtk_init (&argc, &argv);
app_init (app);
GET_UI_ELEMENT (GtkWidget, mainwindow);
GET_UI_ELEMENT (GtkWidget, layout1);
g_signal_connect (G_OBJECT (layout1), "draw",
G_CALLBACK (layout_draw_cb), app);
make_button ("eventbox1", app);
make_button ("eventbox2", app);
gtk_widget_show_all (mainwindow);
gtk_main ();
return 0;
}