1 /*
2 * 0BSD
3 *
4 * BSD Zero Clause License
5 *
6 * Copyright (c) 2019 Hermann Meyer
7 *
8 * Permission to use, copy, modify, and/or distribute this software for any
9 * purpose with or without fee is hereby granted.
10
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
12 * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
13 * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
14 * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15 * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
16 * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17 * PERFORMANCE OF THIS SOFTWARE.
18 *
19 */
20
21 #include "xwidget_private.h"
22
23
_scroll_event(Widget_t * wid,int direction)24 void _scroll_event(Widget_t * wid, int direction) {
25 Adjustment_t *adj = NULL;
26 if (wid->adj_y) {
27 adj = wid->adj_y;
28 } else if(wid->adj_x) {
29 adj = wid->adj_x;
30 }
31 if (adj) {
32 float value = adj->value;
33 switch(adj->type) {
34 case (CL_LOGSCALE):
35 case (CL_LOGARITHMIC):
36 case (CL_CONTINUOS):
37 value = min(adj->max_value,max(adj->min_value,
38 adj->value + (adj->step * direction)));
39 break;
40 case (CL_VIEWPORT):
41 case (CL_ENUM):
42 value = min(adj->max_value,max(adj->min_value,
43 adj->value + (adj->step * -direction)));
44 break;
45 case (CL_TOGGLE):
46 // value = adj->value ? 1.0 : 0.0;
47 break;
48 default:
49 break;
50 }
51 check_value_changed(adj, &value);
52 }
53 }
54
_toggle_event(Widget_t * wid)55 void _toggle_event(Widget_t * wid) {
56 Adjustment_t *adj = NULL;
57 if (wid->adj_y) {
58 adj = wid->adj_y;
59 } else if(wid->adj_x) {
60 adj = wid->adj_x;
61 }
62 if (adj && adj->type != CL_TOGGLE) {
63 adj_set_start_value(wid);
64 }
65 }
66
_check_enum(Widget_t * wid,XButtonEvent * xbutton)67 void _check_enum(Widget_t * wid, XButtonEvent *xbutton) {
68 if (wid->flags & HAS_POINTER && xbutton->button == Button1) {
69 Adjustment_t *adj = NULL;
70 if (wid->adj_y) {
71 adj = wid->adj_y;
72 } else if(wid->adj_x) {
73 adj = wid->adj_x;
74 }
75 if (adj && adj->type == CL_ENUM) {
76 float value = adj->value;
77 value = adj->value + 1.0;
78 if (value>adj->max_value) value = adj->min_value;
79 check_value_changed(adj, &value);
80 }
81 }
82 }
83
_button_press(Widget_t * wid,XButtonEvent * xbutton,void * user_data)84 void _button_press(Widget_t * wid, XButtonEvent *xbutton, void* user_data) {
85 switch(xbutton->button) {
86 case Button1:
87 wid->state = 2;
88 _has_pointer(wid, xbutton);
89 wid->pos_x = xbutton->x;
90 wid->pos_y = xbutton->y;
91 _toggle_event(wid);
92 wid->func.button_press_callback(wid, xbutton, user_data);
93 break;
94 case Button2:
95 debug_print("Button2 \n");
96 break;
97 case Button3:
98 debug_print("Button3 \n");
99 wid->func.button_press_callback(wid, xbutton, user_data);
100 break;
101 case Button4:
102 _scroll_event(wid, 1);
103 break;
104 case Button5:
105 _scroll_event(wid, -1);
106 break;
107 default:
108 break;
109 }
110 }
111
_check_grab(Widget_t * wid,XButtonEvent * xbutton,Xputty * main)112 void _check_grab(Widget_t * wid, XButtonEvent *xbutton, Xputty *main) {
113 if(main->hold_grab != NULL) {
114 Widget_t *view_port = main->hold_grab->childlist->childs[0];
115 if(xbutton->button == Button1) {
116 //if (xbutton->window == view_port->widget) return;
117 XUngrabPointer(main->dpy,CurrentTime);
118 int i = view_port->childlist->elem-1;
119 for(;i>-1;i--) {
120 Widget_t *w = view_port->childlist->childs[i];
121 if (xbutton->window == w->widget) {
122 const char *l = view_port->childlist->childs[i]->label;
123 main->hold_grab->func.button_release_callback
124 (main->hold_grab, &i, &l);
125 break;
126 }
127 }
128 widget_hide(main->hold_grab);
129 main->hold_grab = NULL;
130
131 } else if(xbutton->button == Button4) {
132 _scroll_event(view_port, 1);
133 } else if(xbutton->button == Button5) {
134 _scroll_event(view_port, -1);
135 }
136 }
137 }
138
_propagate_child_expose(Widget_t * wid)139 void _propagate_child_expose(Widget_t *wid) {
140
141 if (childlist_has_child(wid->childlist)) {
142 int i = 0;
143 for(;i<wid->childlist->elem;i++) {
144 Widget_t *w = wid->childlist->childs[i];
145 if (w->flags & USE_TRANSPARENCY) {
146 if(w->flags & FAST_REDRAW)
147 transparent_draw(w, NULL);
148 else expose_widget(w);
149 }
150 }
151 }
152 }
153
_check_keymap(void * w_,XKeyEvent xkey)154 void _check_keymap (void *w_ ,XKeyEvent xkey) {
155 Widget_t *wid = (Widget_t*)w_;
156 int n = 1;
157 int i = 0;
158 for(;i<wid->childlist->elem;i++) {
159 Widget_t *w = wid->childlist->childs[i];
160 if(w->flags & HAS_FOCUS && w->state != 4) {
161 wid=w;
162 break;
163 }
164 }
165 if(wid->app->hold_grab != NULL) {
166 wid = wid->app->hold_grab->childlist->childs[0];
167 n = -1;
168 }
169 int nk = key_mapping(wid->app->dpy, &xkey);
170 if (nk) {
171 switch (nk) {
172 case 3: _set_adj_value(wid, false, 1*n);
173 break;
174 case 4: _set_adj_value(wid, true, 1*n);
175 break;
176 case 5: _set_adj_value(wid, false, -1*n);
177 break;
178 case 6: _set_adj_value(wid, true, -1*n);
179 break;
180 case 10:
181 {
182 int i = 0;
183 for(;i<wid->childlist->elem;i++) {
184 Widget_t *w = wid->childlist->childs[i];
185 if(w->flags & HAS_FOCUS && w->state != 4) {
186 wid=w;
187 break;
188 }
189 }
190 send_button_press_event(wid);
191 send_button_release_event(wid);
192 }
193 break;
194 default:
195 break;
196 }
197 }
198 }
199
_hide_all_tooltips(Widget_t * wid)200 void _hide_all_tooltips(Widget_t *wid) {
201 int i = 0;
202 for(;i<wid->app->childlist->elem;i++) {
203 Widget_t *w = wid->app->childlist->childs[i];
204 if (w->flags & IS_TOOLTIP) {
205 widget_hide(w);
206 }
207 }
208 }
209
_has_pointer(Widget_t * w,XButtonEvent * button)210 void _has_pointer(Widget_t *w, XButtonEvent *button) {
211 XWindowAttributes attrs;
212 XGetWindowAttributes(w->app->dpy, (Window)w->widget, &attrs);
213
214 if ((button->x<attrs.width && button->y<attrs.height) &&
215 (button->x>0 && button->y>0)){
216 w->flags |= HAS_POINTER;
217 } else {
218 w->flags &= ~HAS_POINTER;
219 }
220 }
221
_set_adj_value(void * w_,bool x,int direction)222 void _set_adj_value(void *w_, bool x, int direction) {
223 Widget_t *wid = (Widget_t*)w_;
224 Adjustment_t *adj = NULL;
225 if (x && wid->adj_x) {
226 adj = wid->adj_x;
227 } else if (!x && wid->adj_y) {
228 adj = wid->adj_y;
229 }
230 if (adj) {
231 float value = min(adj->max_value,max(adj->min_value,
232 adj->value + (adj->step * direction)));
233 check_value_changed(adj, &value);
234 }
235 }
236
_dummy1_callback(void * w_,void * _data,void * user_data)237 void _dummy1_callback(void *w_, void* _data, void* user_data) {
238 debug_print("Widget_t _dummy callback\n");
239 }
240
_dummy_callback(void * w_,void * user_data)241 void _dummy_callback(void *w_, void* user_data) {
242 debug_print("Widget_t _dummy callback\n");
243 }
244
_resize_surface(Widget_t * wid,int width,int height)245 void _resize_surface(Widget_t *wid, int width, int height) {
246 wid->width = width;
247 wid->height = height;
248 cairo_xlib_surface_set_size( wid->surface, wid->width, wid->height);
249 cairo_font_face_t *ff = cairo_get_font_face(wid->crb);
250 cairo_destroy(wid->crb);
251 cairo_surface_destroy(wid->buffer);
252 wid->buffer = cairo_surface_create_similar (wid->surface,
253 CAIRO_CONTENT_COLOR_ALPHA, width, height);
254 assert(cairo_surface_status(wid->buffer) == CAIRO_STATUS_SUCCESS);
255 wid->crb = cairo_create (wid->buffer);
256 cairo_set_font_face(wid->crb, ff);
257 }
258
_resize_childs(Widget_t * wid)259 void _resize_childs(Widget_t *wid) {
260 if(!childlist_has_child(wid->childlist)) return;
261 int i = 0;
262 for(;i<wid->childlist->elem;i++) {
263 Widget_t *w = wid->childlist->childs[i];
264 switch(w->scale.gravity) {
265 case(NORTHWEST):
266 XResizeWindow (wid->app->dpy, w->widget, max(1,
267 w->scale.init_width - (wid->scale.scale_x)),
268 max(1,w->scale.init_height - (wid->scale.scale_y)));
269 break;
270 case(NORTHEAST):
271 XResizeWindow (wid->app->dpy, w->widget, max(1,
272 w->scale.init_width - (wid->scale.scale_x)), w->height);
273 break;
274 case(SOUTHWEST):
275 XMoveWindow(wid->app->dpy,w->widget,w->scale.init_x-wid->scale.scale_x,
276 w->scale.init_y-wid->scale.scale_y);
277
278 break;
279 case(SOUTHEAST):
280 XMoveWindow(wid->app->dpy,w->widget,w->scale.init_x,
281 w->scale.init_y-wid->scale.scale_y);
282 break;
283 case(CENTER):
284 XMoveWindow(wid->app->dpy,w->widget,w->scale.init_x /
285 wid->scale.cscale_x,w->scale.init_y / wid->scale.cscale_y);
286 XResizeWindow (wid->app->dpy, w->widget, max(1,
287 w->scale.init_width / (wid->scale.cscale_x)),
288 max(1,w->scale.init_height / (wid->scale.cscale_y)));
289 break;
290 case(ASPECT):
291 XMoveWindow(wid->app->dpy,w->widget,(
292 (w->scale.init_x + w->scale.init_width/2.0) /
293 wid->scale.cscale_x) - w->width/2.0,
294 ((w->scale.init_y + w->scale.init_height/2.0) /
295 wid->scale.cscale_y)- w->height/2.0) ;
296 XResizeWindow (wid->app->dpy, w->widget, max(1,
297 w->scale.init_width / (wid->scale.ascale)),
298 max(1,w->scale.init_height / (wid->scale.ascale)));
299
300 break;
301 case(MENUITEM):
302 XResizeWindow (wid->app->dpy, w->widget, max(1,
303 w->scale.init_width - (wid->scale.scale_x)-5), w->scale.init_height);
304 break;
305 case(NONE):
306 break;
307 default:
308 break;
309 }
310 w->func.configure_notify_callback(w,NULL);
311 }
312 }
313