• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2013 Collabora Ltd.
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 <assert.h>
27 #include <stdint.h>
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <stdbool.h>
32 #include <errno.h>
33 
34 #include <linux/input.h>
35 #include <cairo.h>
36 #include <wayland-util.h>
37 
38 #include "shared/helpers.h"
39 #include "window.h"
40 
41 struct stacking {
42 	struct display *display;
43 	struct window *root_window;
44 };
45 
46 static void
47 button_handler(struct widget *widget,
48                struct input *input, uint32_t time,
49                uint32_t button,
50                enum wl_pointer_button_state state, void *data);
51 static void
52 key_handler(struct window *window,
53             struct input *input, uint32_t time,
54             uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
55             void *data);
56 static void
57 keyboard_focus_handler(struct window *window,
58 		       struct input *device, void *data);
59 static void
60 fullscreen_handler(struct window *window, void *data);
61 static void
62 redraw_handler(struct widget *widget, void *data);
63 
64 /* Iff parent_window is set, the new window will be transient. */
65 static struct window *
new_window(struct stacking * stacking,struct window * parent_window)66 new_window(struct stacking *stacking, struct window *parent_window)
67 {
68 	struct window *new_window;
69 	struct widget *new_widget;
70 
71 	new_window = window_create(stacking->display);
72 	window_set_parent(new_window, parent_window);
73 
74 	new_widget = window_frame_create(new_window, new_window);
75 
76 	window_set_title(new_window, "Stacking Test");
77 	window_set_key_handler(new_window, key_handler);
78 	window_set_keyboard_focus_handler(new_window, keyboard_focus_handler);
79 	window_set_fullscreen_handler(new_window, fullscreen_handler);
80 	widget_set_button_handler(new_widget, button_handler);
81 	widget_set_redraw_handler(new_widget, redraw_handler);
82 	window_set_user_data(new_window, stacking);
83 
84 	window_schedule_resize(new_window, 300, 300);
85 
86 	return new_window;
87 }
88 
89 static void
show_popup_cb(void * data,struct input * input,int index)90 show_popup_cb(void *data, struct input *input, int index)
91 {
92 	/* Ignore the selected menu item. */
93 }
94 
95 static void
show_popup(struct stacking * stacking,struct input * input,uint32_t time,struct window * window)96 show_popup(struct stacking *stacking, struct input *input, uint32_t time,
97            struct window *window)
98 {
99 	int32_t x, y;
100 	static const char *entries[] = {
101 		"Test Entry",
102 		"Another Test Entry",
103 	};
104 
105 	input_get_position(input, &x, &y);
106 	window_show_menu(stacking->display, input, time, window, x, y,
107 	                 show_popup_cb, entries, ARRAY_LENGTH(entries));
108 }
109 
110 static void
button_handler(struct widget * widget,struct input * input,uint32_t time,uint32_t button,enum wl_pointer_button_state state,void * data)111 button_handler(struct widget *widget,
112                struct input *input, uint32_t time,
113                uint32_t button,
114                enum wl_pointer_button_state state, void *data)
115 {
116 	struct stacking *stacking = data;
117 
118 	switch (button) {
119 	case BTN_RIGHT:
120 		if (state == WL_POINTER_BUTTON_STATE_PRESSED)
121 			show_popup(stacking, input, time,
122 			           widget_get_user_data(widget));
123 		break;
124 
125 	case BTN_LEFT:
126 	default:
127 		break;
128 	}
129 }
130 
131 static void
key_handler(struct window * window,struct input * input,uint32_t time,uint32_t key,uint32_t sym,enum wl_keyboard_key_state state,void * data)132 key_handler(struct window *window,
133             struct input *input, uint32_t time,
134             uint32_t key, uint32_t sym, enum wl_keyboard_key_state state,
135             void *data)
136 {
137 	struct stacking *stacking = data;
138 
139 	if (state != WL_KEYBOARD_KEY_STATE_PRESSED)
140 		return;
141 
142 	switch (sym) {
143 	case XKB_KEY_f:
144 		fullscreen_handler(window, data);
145 		break;
146 
147 	case XKB_KEY_m:
148 		window_set_maximized(window, !window_is_maximized(window));
149 		break;
150 
151 	case XKB_KEY_n:
152 		/* New top-level window. */
153 		new_window(stacking, NULL);
154 		break;
155 
156 	case XKB_KEY_p:
157 		show_popup(stacking, input, time, window);
158 		break;
159 
160 	case XKB_KEY_q:
161 		exit (0);
162 		break;
163 
164 	case XKB_KEY_t:
165 		/* New transient window. */
166 		new_window(stacking, window);
167 		break;
168 
169 	default:
170 		break;
171 	}
172 }
173 
174 static void
keyboard_focus_handler(struct window * window,struct input * device,void * data)175 keyboard_focus_handler(struct window *window,
176 		       struct input *device, void *data)
177 {
178 	window_schedule_redraw(window);
179 }
180 
181 static void
fullscreen_handler(struct window * window,void * data)182 fullscreen_handler(struct window *window, void *data)
183 {
184 	window_set_fullscreen(window, !window_is_fullscreen(window));
185 }
186 
187 static void
188 draw_string(cairo_t *cr,
189             const char *fmt, ...) WL_PRINTF(2, 3);
190 
191 static void
draw_string(cairo_t * cr,const char * fmt,...)192 draw_string(cairo_t *cr,
193             const char *fmt, ...)
194 {
195 	char buffer[4096];
196 	char *p, *end;
197 	va_list argp;
198 	cairo_text_extents_t text_extents;
199 	cairo_font_extents_t font_extents;
200 
201 	cairo_save(cr);
202 
203 	cairo_select_font_face(cr, "sans",
204 	                       CAIRO_FONT_SLANT_NORMAL,
205 	                       CAIRO_FONT_WEIGHT_NORMAL);
206 	cairo_set_font_size(cr, 14);
207 
208 	cairo_font_extents(cr, &font_extents);
209 
210 	va_start(argp, fmt);
211 
212 	vsnprintf(buffer, sizeof(buffer), fmt, argp);
213 
214 	p = buffer;
215 	while (*p) {
216 		end = strchr(p, '\n');
217 		if (end)
218 			*end = 0;
219 
220 		cairo_show_text(cr, p);
221 		cairo_text_extents(cr, p, &text_extents);
222 		cairo_rel_move_to(cr, -text_extents.x_advance, font_extents.height);
223 
224 		if (end)
225 			p = end + 1;
226 		else
227 			break;
228 	}
229 
230 	va_end(argp);
231 
232 	cairo_restore(cr);
233 }
234 
235 static void
set_window_background_colour(cairo_t * cr,struct window * window)236 set_window_background_colour(cairo_t *cr, struct window *window)
237 {
238 	if (window_get_parent(window))
239 		cairo_set_source_rgba(cr, 0.0, 1.0, 0.0, 0.4);
240 	else if (window_is_maximized(window))
241 		cairo_set_source_rgba(cr, 1.0, 1.0, 0.0, 0.6);
242 	else if (window_is_fullscreen(window))
243 		cairo_set_source_rgba(cr, 0.0, 1.0, 1.0, 0.6);
244 	else
245 		cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 1.0);
246 }
247 
248 static void
redraw_handler(struct widget * widget,void * data)249 redraw_handler(struct widget *widget, void *data)
250 {
251 	struct window *window;
252 	struct rectangle allocation;
253 	cairo_t *cr;
254 
255 	widget_get_allocation(widget, &allocation);
256 	window = widget_get_user_data(widget);
257 
258 	cr = widget_cairo_create(widget);
259 	cairo_translate(cr, allocation.x, allocation.y);
260 
261 	/* Draw background. */
262 	cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
263 	set_window_background_colour(cr, window);
264 	cairo_rectangle(cr, 0, 0, allocation.width, allocation.height);
265 	cairo_fill(cr);
266 
267 	/* Print the instructions. */
268 	cairo_move_to(cr, 5, 15);
269 	cairo_set_source_rgb(cr, 1.0, 1.0, 1.0);
270 
271 	draw_string(cr,
272 	            "Window: %p\n"
273 	            "Fullscreen? %u\n"
274 	            "Maximized? %u\n"
275 	            "Transient? %u\n"
276 	            "Keys: (f)ullscreen, (m)aximize,\n"
277 	            "      (n)ew window, (p)opup,\n"
278 	            "      (q)uit, (t)ransient window\n",
279 	            window, window_is_fullscreen(window),
280 	            window_is_maximized(window), window_get_parent(window) ? 1 : 0);
281 
282 	cairo_destroy(cr);
283 }
284 
285 int
main(int argc,char * argv[])286 main(int argc, char *argv[])
287 {
288 	struct stacking stacking;
289 
290 	memset(&stacking, 0, sizeof stacking);
291 
292 	stacking.display = display_create(&argc, argv);
293 	if (stacking.display == NULL) {
294 		fprintf(stderr, "Failed to create display: %s\n",
295 			strerror(errno));
296 		return -1;
297 	}
298 
299 	display_set_user_data(stacking.display, &stacking);
300 
301 	stacking.root_window = new_window(&stacking, NULL);
302 
303 	display_run(stacking.display);
304 
305 	window_destroy(stacking.root_window);
306 	display_destroy(stacking.display);
307 
308 	return 0;
309 }
310