blob: a707037c46b7b4070da64a07668f002a9350530c [file] [log] [blame]
Pekka Paalanen69201902012-01-20 11:09:13 +02001/*
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 <stdint.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <cairo.h>
28#include <math.h>
29#include <assert.h>
30
31#include <linux/input.h>
32#include <wayland-client.h>
33
34#include "window.h"
35
36#include <X11/keysym.h>
37
38struct clickdot {
39 struct display *display;
40 struct window *window;
41 struct widget *widget;
42 struct window *menu;
43 int32_t width;
44
45 struct {
46 double current;
47 double target;
48 double previous;
49 } height;
50 struct wl_callback *frame_callback;
51};
52
53static void
54frame_callback(void *data, struct wl_callback *callback, uint32_t time)
55{
56 struct clickdot *clickdot = data;
57 double force, height;
58
59 assert(!callback || callback == clickdot->frame_callback);
60
61 height = clickdot->height.current;
62 force = (clickdot->height.target - height) / 10.0 +
63 (clickdot->height.previous - height);
64
65 clickdot->height.current =
66 height + (height - clickdot->height.previous) + force;
67 clickdot->height.previous = height;
68
69 if (clickdot->height.current >= 400) {
70 clickdot->height.current = 400;
71 clickdot->height.previous = 400;
72 }
73
74 if (clickdot->height.current <= 200) {
75 clickdot->height.current = 200;
76 clickdot->height.previous = 200;
77 }
78
79 widget_schedule_resize(clickdot->widget, clickdot->width, height + 0.5);
80
81 if (clickdot->frame_callback) {
82 wl_callback_destroy(clickdot->frame_callback);
83 clickdot->frame_callback = NULL;
84 }
85}
86
87static const struct wl_callback_listener listener = {
88 frame_callback
89};
90
91static void
92redraw_handler(struct widget *widget, void *data)
93{
94 struct clickdot *clickdot = data;
95 cairo_surface_t *surface;
96 cairo_t *cr;
97 struct rectangle allocation;
98
99 widget_get_allocation(clickdot->widget, &allocation);
100
101 surface = window_get_surface(clickdot->window);
102
103 cr = cairo_create(surface);
104 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
105 cairo_rectangle(cr,
106 allocation.x,
107 allocation.y,
108 allocation.width,
109 allocation.height);
110 cairo_set_source_rgba(cr, 0, 0, 0, 0.8);
111 cairo_fill(cr);
112 cairo_destroy(cr);
113
114 cairo_surface_destroy(surface);
115
116 if (fabs(clickdot->height.previous - clickdot->height.target) > 0.1) {
117 clickdot->frame_callback =
118 wl_surface_frame(
119 window_get_wl_surface(clickdot->window));
120 wl_callback_add_listener(clickdot->frame_callback, &listener,
121 clickdot);
122 }
123
124}
125
126static void
127keyboard_focus_handler(struct window *window,
128 struct input *device, void *data)
129{
130 struct clickdot *clickdot = data;
131
132 window_schedule_redraw(clickdot->window);
133}
134
135static void
136key_handler(struct window *window, struct input *input, uint32_t time,
137 uint32_t key, uint32_t sym, uint32_t state, void *data)
138{
139 struct clickdot *clickdot = data;
140
141 if (state == 0)
142 return;
143
144 switch (sym) {
145 case XK_Down:
146 clickdot->height.target = 400;
147 frame_callback(clickdot, NULL, 0);
148 break;
149 case XK_Up:
150 clickdot->height.target = 200;
151 frame_callback(clickdot, NULL, 0);
152 break;
153 case XK_Escape:
154 display_exit(clickdot->display);
155 break;
156 }
157}
158
159static void
160menu_func(struct window *window, int index, void *user_data)
161{
162 fprintf(stderr, "picked entry %d\n", index);
163}
164
165static void
166show_menu(struct clickdot *clickdot, struct input *input, uint32_t time)
167{
168 int32_t x, y;
169 static const char *entries[] = {
170 "Roy", "Pris", "Leon", "Zhora"
171 };
172
173 input_get_position(input, &x, &y);
174 window_show_menu(clickdot->display, input, time, clickdot->window,
175 x - 10, y - 10, menu_func, entries, 4);
176}
177
178static void
179button_handler(struct widget *widget,
180 struct input *input, uint32_t time,
181 int button, int state, void *data)
182{
183 struct clickdot *clickdot = data;
184
185 switch (button) {
186 case BTN_RIGHT:
187 if (state)
188 show_menu(clickdot, input, time);
189 break;
190 }
191}
192
193static struct clickdot *
194clickdot_create(struct display *display)
195{
196 struct clickdot *clickdot;
197 int32_t height;
198
199 clickdot = malloc(sizeof *clickdot);
200 if (clickdot == NULL)
201 return clickdot;
202 memset(clickdot, 0, sizeof *clickdot);
203
204 clickdot->window = window_create(display, 500, 400);
205 clickdot->widget = frame_create(clickdot->window, clickdot);
206 window_set_title(clickdot->window, "Wayland Resizor");
207 clickdot->display = display;
208
209 window_set_key_handler(clickdot->window, key_handler);
210 window_set_user_data(clickdot->window, clickdot);
211 widget_set_redraw_handler(clickdot->widget, redraw_handler);
212 window_set_keyboard_focus_handler(clickdot->window,
213 keyboard_focus_handler);
214
215 clickdot->width = 300;
216 clickdot->height.current = 400;
217 clickdot->height.previous = clickdot->height.current;
218 clickdot->height.target = clickdot->height.current;
219 height = clickdot->height.current + 0.5;
220
221 widget_set_button_handler(clickdot->widget, button_handler);
222
223 widget_schedule_resize(clickdot->widget, clickdot->width, height);
224
225 return clickdot;
226}
227
228static void
229clickdot_destroy(struct clickdot *clickdot)
230{
231 if (clickdot->frame_callback)
232 wl_callback_destroy(clickdot->frame_callback);
233
234 widget_destroy(clickdot->widget);
235 window_destroy(clickdot->window);
236 free(clickdot);
237}
238
239int
240main(int argc, char *argv[])
241{
242 struct display *display;
243 struct clickdot *clickdot;
244
245 display = display_create(&argc, &argv, NULL);
246 if (display == NULL) {
247 fprintf(stderr, "failed to create display: %m\n");
248 return -1;
249 }
250
251 clickdot = clickdot_create(display);
252
253 display_run(display);
254
255 clickdot_destroy(clickdot);
256 display_destroy(display);
257
258 return 0;
259}