1 /*
2 * Copyright © 2008 Kristian Høgsberg
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24 #include "config.h"
25
26 #include <stdint.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <time.h>
31 #include <math.h>
32 #include <cairo.h>
33 #include <errno.h>
34 #include <sys/time.h>
35
36 #include <linux/input.h>
37 #include <wayland-client.h>
38 #include "window.h"
39
40 struct flower {
41 struct display *display;
42 struct window *window;
43 struct widget *widget;
44 int width, height;
45 };
46
47 static void
set_random_color(cairo_t * cr)48 set_random_color(cairo_t *cr)
49 {
50 cairo_set_source_rgba(cr,
51 0.5 + (random() % 50) / 49.0,
52 0.5 + (random() % 50) / 49.0,
53 0.5 + (random() % 50) / 49.0,
54 0.5 + (random() % 100) / 99.0);
55 }
56
57
58 static void
draw_stuff(cairo_surface_t * surface,int width,int height)59 draw_stuff(cairo_surface_t *surface, int width, int height)
60 {
61 const int petal_count = 3 + random() % 5;
62 const double r1 = 60 + random() % 35;
63 const double r2 = 20 + random() % 40;
64 const double u = (10 + random() % 90) / 100.0;
65 const double v = (random() % 90) / 100.0;
66
67 cairo_t *cr;
68 int i;
69 double t, dt = 2 * M_PI / (petal_count * 2);
70 double x1, y1, x2, y2, x3, y3;
71
72 cr = cairo_create(surface);
73 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
74 cairo_set_source_rgba(cr, 0, 0, 0, 0);
75 cairo_paint(cr);
76
77 cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
78 cairo_translate(cr, width / 2, height / 2);
79 cairo_move_to(cr, cos(0) * r1, sin(0) * r1);
80 for (t = 0, i = 0; i < petal_count; i++, t += dt * 2) {
81 x1 = cos(t) * r1;
82 y1 = sin(t) * r1;
83 x2 = cos(t + dt) * r2;
84 y2 = sin(t + dt) * r2;
85 x3 = cos(t + 2 * dt) * r1;
86 y3 = sin(t + 2 * dt) * r1;
87
88 cairo_curve_to(cr,
89 x1 - y1 * u, y1 + x1 * u,
90 x2 + y2 * v, y2 - x2 * v,
91 x2, y2);
92
93 cairo_curve_to(cr,
94 x2 - y2 * v, y2 + x2 * v,
95 x3 + y3 * u, y3 - x3 * u,
96 x3, y3);
97 }
98
99 cairo_close_path(cr);
100 set_random_color(cr);
101 cairo_fill_preserve(cr);
102 set_random_color(cr);
103 cairo_stroke(cr);
104
105 cairo_destroy(cr);
106 }
107
108 static void
resize_handler(struct widget * widget,int32_t width,int32_t height,void * data)109 resize_handler(struct widget *widget,
110 int32_t width, int32_t height, void *data)
111 {
112 struct flower *flower = data;
113
114 /* Don't resize me */
115 widget_set_size(flower->widget, flower->width, flower->height);
116 }
117
118 static void
redraw_handler(struct widget * widget,void * data)119 redraw_handler(struct widget *widget, void *data)
120 {
121 struct flower *flower = data;
122 cairo_surface_t *surface;
123
124 surface = window_get_surface(flower->window);
125 if (surface == NULL ||
126 cairo_surface_status(surface) != CAIRO_STATUS_SUCCESS) {
127 fprintf(stderr, "failed to create cairo egl surface\n");
128 return;
129 }
130
131 draw_stuff(surface, flower->width, flower->height);
132 cairo_surface_destroy(surface);
133 }
134
135 static void
button_handler(struct widget * widget,struct input * input,uint32_t time,uint32_t button,enum wl_pointer_button_state state,void * data)136 button_handler(struct widget *widget,
137 struct input *input, uint32_t time,
138 uint32_t button, enum wl_pointer_button_state state, void *data)
139 {
140 struct flower *flower = data;
141
142 switch (button) {
143 case BTN_LEFT:
144 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
145 window_move(flower->window, input,
146 display_get_serial(flower->display));
147 break;
148 case BTN_MIDDLE:
149 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
150 widget_schedule_redraw(widget);
151 break;
152 case BTN_RIGHT:
153 if (state == WL_POINTER_BUTTON_STATE_PRESSED)
154 window_show_frame_menu(flower->window, input, time);
155 break;
156 }
157 }
158
159 static void
touch_down_handler(struct widget * widget,struct input * input,uint32_t serial,uint32_t time,int32_t id,float x,float y,void * data)160 touch_down_handler(struct widget *widget, struct input *input,
161 uint32_t serial, uint32_t time, int32_t id,
162 float x, float y, void *data)
163 {
164 struct flower *flower = data;
165 window_move(flower->window, input, display_get_serial(flower->display));
166 }
167
main(int argc,char * argv[])168 int main(int argc, char *argv[])
169 {
170 struct flower flower;
171 struct display *d;
172 struct timeval tv;
173
174 d = display_create(&argc, argv);
175 if (d == NULL) {
176 fprintf(stderr, "failed to create display: %s\n",
177 strerror(errno));
178 return -1;
179 }
180
181 gettimeofday(&tv, NULL);
182 srandom(tv.tv_usec);
183
184 flower.width = 200;
185 flower.height = 200;
186 flower.display = d;
187 flower.window = window_create(d);
188 flower.widget = window_add_widget(flower.window, &flower);
189 window_set_title(flower.window, "Flower");
190
191 widget_set_resize_handler(flower.widget, resize_handler);
192 widget_set_redraw_handler(flower.widget, redraw_handler);
193 widget_set_button_handler(flower.widget, button_handler);
194 widget_set_default_cursor(flower.widget, CURSOR_HAND1);
195 widget_set_touch_down_handler(flower.widget, touch_down_handler);
196
197 window_schedule_resize(flower.window, flower.width, flower.height);
198
199 display_run(d);
200
201 widget_destroy(flower.widget);
202 window_destroy(flower.window);
203 display_destroy(d);
204
205 return 0;
206 }
207