compositor-x11: Rename the output make to "weston-X11"
[platform/upstream/weston.git] / clients / resizor.c
1 /*
2  * Copyright © 2010 Intel Corporation
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #include "config.h"
24
25 #include <stdint.h>
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <cairo.h>
30 #include <math.h>
31 #include <assert.h>
32
33 #include <linux/input.h>
34 #include <wayland-client.h>
35
36 #include "window.h"
37
38 struct spring {
39         double current;
40         double target;
41         double previous;
42 };
43
44 struct resizor {
45         struct display *display;
46         struct window *window;
47         struct widget *widget;
48         struct window *menu;
49         struct spring width;
50         struct spring height;
51         struct wl_callback *frame_callback;
52 };
53
54 static void
55 spring_update(struct spring *spring)
56 {
57         double current, force;
58
59         current = spring->current;
60         force = (spring->target - current) / 20.0 +
61                 (spring->previous - current);
62
63         spring->current = current + (current - spring->previous) + force;
64         spring->previous = current;
65 }
66
67 static int
68 spring_done(struct spring *spring)
69 {
70         return fabs(spring->previous - spring->target) < 0.1;
71 }
72
73 static const struct wl_callback_listener listener;
74
75 static void
76 frame_callback(void *data, struct wl_callback *callback, uint32_t time)
77 {
78         struct resizor *resizor = data;
79
80         assert(!callback || callback == resizor->frame_callback);
81
82         if (resizor->frame_callback) {
83                 wl_callback_destroy(resizor->frame_callback);
84                 resizor->frame_callback = NULL;
85         }
86
87         if (window_is_maximized(resizor->window))
88                 return;
89
90         spring_update(&resizor->width);
91         spring_update(&resizor->height);
92
93         widget_schedule_resize(resizor->widget,
94                                resizor->width.current + 0.5,
95                                resizor->height.current + 0.5);
96
97         if (!spring_done(&resizor->width) || !spring_done(&resizor->height)) {
98                 resizor->frame_callback =
99                         wl_surface_frame(
100                                 window_get_wl_surface(resizor->window));
101                 wl_callback_add_listener(resizor->frame_callback, &listener,
102                                          resizor);
103         }
104 }
105
106 static const struct wl_callback_listener listener = {
107         frame_callback
108 };
109
110 static void
111 redraw_handler(struct widget *widget, void *data)
112 {
113         struct resizor *resizor = data;
114         cairo_surface_t *surface;
115         cairo_t *cr;
116         struct rectangle allocation;
117
118         widget_get_allocation(resizor->widget, &allocation);
119
120         surface = window_get_surface(resizor->window);
121
122         cr = cairo_create(surface);
123         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
124         cairo_rectangle(cr,
125                         allocation.x,
126                         allocation.y,
127                         allocation.width,
128                         allocation.height);
129         cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
130         cairo_fill(cr);
131         cairo_destroy(cr);
132
133         cairo_surface_destroy(surface);
134 }
135
136 static void
137 keyboard_focus_handler(struct window *window,
138                        struct input *device, void *data)
139 {
140         struct resizor *resizor = data;
141
142         window_schedule_redraw(resizor->window);
143 }
144
145 static void
146 key_handler(struct window *window, struct input *input, uint32_t time,
147             uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
148             void *data)
149 {
150         struct resizor *resizor = data;
151         struct rectangle allocation;
152
153         if (state == WL_KEYBOARD_KEY_STATE_RELEASED)
154                 return;
155
156         window_get_allocation(resizor->window, &allocation);
157         resizor->width.current = allocation.width;
158         if (spring_done(&resizor->width))
159                 resizor->width.target = allocation.width;
160         resizor->height.current = allocation.height;
161         if (spring_done(&resizor->height))
162                 resizor->height.target = allocation.height;
163
164         switch (sym) {
165         case XKB_KEY_Up:
166                 if (allocation.height < 400)
167                         break;
168
169                 resizor->height.target = allocation.height - 200;
170                 break;
171
172         case XKB_KEY_Down:
173                 if (allocation.height > 1000)
174                         break;
175
176                 resizor->height.target = allocation.height + 200;
177                 break;
178
179         case XKB_KEY_Left:
180                 if (allocation.width < 400)
181                         break;
182
183                 resizor->width.target = allocation.width - 200;
184                 break;
185
186         case XKB_KEY_Right:
187                 if (allocation.width > 1000)
188                         break;
189
190                 resizor->width.target = allocation.width + 200;
191                 break;
192
193         case XKB_KEY_Escape:
194                 display_exit(resizor->display);
195                 break;
196         }
197
198         if (!resizor->frame_callback)
199                 frame_callback(resizor, NULL, 0);
200 }
201
202 static void
203 menu_func(void *data, struct input *input, int index)
204 {
205         fprintf(stderr, "picked entry %d\n", index);
206 }
207
208 static void
209 show_menu(struct resizor *resizor, struct input *input, uint32_t time)
210 {
211         int32_t x, y;
212         static const char *entries[] = {
213                 "Roy", "Pris", "Leon", "Zhora"
214         };
215
216         input_get_position(input, &x, &y);
217         window_show_menu(resizor->display, input, time, resizor->window,
218                          x - 10, y - 10, menu_func, entries, 4);
219 }
220
221 static void
222 button_handler(struct widget *widget,
223                struct input *input, uint32_t time,
224                uint32_t button, enum wl_pointer_button_state state, void *data)
225 {
226         struct resizor *resizor = data;
227
228         switch (button) {
229         case BTN_RIGHT:
230                 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
231                         show_menu(resizor, input, time);
232                 break;
233         }
234 }
235
236 static struct resizor *
237 resizor_create(struct display *display)
238 {
239         struct resizor *resizor;
240
241         resizor = xzalloc(sizeof *resizor);
242         resizor->window = window_create(display);
243         resizor->widget = window_frame_create(resizor->window, resizor);
244         window_set_title(resizor->window, "Wayland Resizor");
245         resizor->display = display;
246
247         window_set_key_handler(resizor->window, key_handler);
248         window_set_user_data(resizor->window, resizor);
249         widget_set_redraw_handler(resizor->widget, redraw_handler);
250         window_set_keyboard_focus_handler(resizor->window,
251                                           keyboard_focus_handler);
252
253         widget_set_button_handler(resizor->widget, button_handler);
254
255         resizor->height.previous = 400;
256         resizor->height.current = 400;
257         resizor->height.target = 400;
258
259         resizor->width.previous = 400;
260         resizor->width.current = 400;
261         resizor->width.target = 400;
262
263         widget_schedule_resize(resizor->widget, 400, 400);
264
265         return resizor;
266 }
267
268 static void
269 resizor_destroy(struct resizor *resizor)
270 {
271         if (resizor->frame_callback)
272                 wl_callback_destroy(resizor->frame_callback);
273
274         widget_destroy(resizor->widget);
275         window_destroy(resizor->window);
276         free(resizor);
277 }
278
279 int
280 main(int argc, char *argv[])
281 {
282         struct display *display;
283         struct resizor *resizor;
284
285         display = display_create(&argc, argv);
286         if (display == NULL) {
287                 fprintf(stderr, "failed to create display: %m\n");
288                 return -1;
289         }
290
291         resizor = resizor_create(display);
292
293         display_run(display);
294
295         resizor_destroy(resizor);
296         display_destroy(display);
297
298         return 0;
299 }