1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright © 2011-2014 Intel Corporation
3*4882a593Smuzhiyun *
4*4882a593Smuzhiyun * Permission to use, copy, modify, distribute, and sell this software
5*4882a593Smuzhiyun * and its documentation for any purpose is hereby granted without
6*4882a593Smuzhiyun * fee, provided that the above copyright notice appear in all copies
7*4882a593Smuzhiyun * and that both that copyright notice and this permission notice
8*4882a593Smuzhiyun * appear in supporting documentation, and that the name of the
9*4882a593Smuzhiyun * copyright holders not be used in advertising or publicity
10*4882a593Smuzhiyun * pertaining to distribution of the software without specific,
11*4882a593Smuzhiyun * written prior permission. The copyright holders make no
12*4882a593Smuzhiyun * representations about the suitability of this software for any
13*4882a593Smuzhiyun * purpose. It is provided "as is" without express or implied
14*4882a593Smuzhiyun * warranty.
15*4882a593Smuzhiyun *
16*4882a593Smuzhiyun * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
17*4882a593Smuzhiyun * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
18*4882a593Smuzhiyun * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
19*4882a593Smuzhiyun * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
20*4882a593Smuzhiyun * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
21*4882a593Smuzhiyun * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
22*4882a593Smuzhiyun * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
23*4882a593Smuzhiyun * SOFTWARE.
24*4882a593Smuzhiyun */
25*4882a593Smuzhiyun
26*4882a593Smuzhiyun #ifdef HAVE_DIX_CONFIG_H
27*4882a593Smuzhiyun #include <dix-config.h>
28*4882a593Smuzhiyun #endif
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun #include "xwayland.h"
31*4882a593Smuzhiyun #include <randrstr.h>
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define ALL_ROTATIONS (RR_Rotate_0 | \
34*4882a593Smuzhiyun RR_Rotate_90 | \
35*4882a593Smuzhiyun RR_Rotate_180 | \
36*4882a593Smuzhiyun RR_Rotate_270 | \
37*4882a593Smuzhiyun RR_Reflect_X | \
38*4882a593Smuzhiyun RR_Reflect_Y)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun static void xwl_output_get_xdg_output(struct xwl_output *xwl_output);
41*4882a593Smuzhiyun
42*4882a593Smuzhiyun static Rotation
wl_transform_to_xrandr(enum wl_output_transform transform)43*4882a593Smuzhiyun wl_transform_to_xrandr(enum wl_output_transform transform)
44*4882a593Smuzhiyun {
45*4882a593Smuzhiyun switch (transform) {
46*4882a593Smuzhiyun default:
47*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_NORMAL:
48*4882a593Smuzhiyun return RR_Rotate_0;
49*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_90:
50*4882a593Smuzhiyun return RR_Rotate_90;
51*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_180:
52*4882a593Smuzhiyun return RR_Rotate_180;
53*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_270:
54*4882a593Smuzhiyun return RR_Rotate_270;
55*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_FLIPPED:
56*4882a593Smuzhiyun return RR_Reflect_X | RR_Rotate_0;
57*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_FLIPPED_90:
58*4882a593Smuzhiyun return RR_Reflect_X | RR_Rotate_90;
59*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_FLIPPED_180:
60*4882a593Smuzhiyun return RR_Reflect_X | RR_Rotate_180;
61*4882a593Smuzhiyun case WL_OUTPUT_TRANSFORM_FLIPPED_270:
62*4882a593Smuzhiyun return RR_Reflect_X | RR_Rotate_270;
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun }
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static int
wl_subpixel_to_xrandr(int subpixel)67*4882a593Smuzhiyun wl_subpixel_to_xrandr(int subpixel)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun switch (subpixel) {
70*4882a593Smuzhiyun default:
71*4882a593Smuzhiyun case WL_OUTPUT_SUBPIXEL_UNKNOWN:
72*4882a593Smuzhiyun return SubPixelUnknown;
73*4882a593Smuzhiyun case WL_OUTPUT_SUBPIXEL_NONE:
74*4882a593Smuzhiyun return SubPixelNone;
75*4882a593Smuzhiyun case WL_OUTPUT_SUBPIXEL_HORIZONTAL_RGB:
76*4882a593Smuzhiyun return SubPixelHorizontalRGB;
77*4882a593Smuzhiyun case WL_OUTPUT_SUBPIXEL_HORIZONTAL_BGR:
78*4882a593Smuzhiyun return SubPixelHorizontalBGR;
79*4882a593Smuzhiyun case WL_OUTPUT_SUBPIXEL_VERTICAL_RGB:
80*4882a593Smuzhiyun return SubPixelVerticalRGB;
81*4882a593Smuzhiyun case WL_OUTPUT_SUBPIXEL_VERTICAL_BGR:
82*4882a593Smuzhiyun return SubPixelVerticalBGR;
83*4882a593Smuzhiyun }
84*4882a593Smuzhiyun }
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun static void
output_handle_geometry(void * data,struct wl_output * wl_output,int x,int y,int physical_width,int physical_height,int subpixel,const char * make,const char * model,int transform)87*4882a593Smuzhiyun output_handle_geometry(void *data, struct wl_output *wl_output, int x, int y,
88*4882a593Smuzhiyun int physical_width, int physical_height, int subpixel,
89*4882a593Smuzhiyun const char *make, const char *model, int transform)
90*4882a593Smuzhiyun {
91*4882a593Smuzhiyun struct xwl_output *xwl_output = data;
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun RROutputSetPhysicalSize(xwl_output->randr_output,
94*4882a593Smuzhiyun physical_width, physical_height);
95*4882a593Smuzhiyun RROutputSetSubpixelOrder(xwl_output->randr_output,
96*4882a593Smuzhiyun wl_subpixel_to_xrandr(subpixel));
97*4882a593Smuzhiyun
98*4882a593Smuzhiyun /* Apply the change from wl_output only if xdg-output is not supported */
99*4882a593Smuzhiyun if (!xwl_output->xdg_output) {
100*4882a593Smuzhiyun xwl_output->x = x;
101*4882a593Smuzhiyun xwl_output->y = y;
102*4882a593Smuzhiyun }
103*4882a593Smuzhiyun xwl_output->rotation = wl_transform_to_xrandr(transform);
104*4882a593Smuzhiyun }
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun static void
output_handle_mode(void * data,struct wl_output * wl_output,uint32_t flags,int width,int height,int refresh)107*4882a593Smuzhiyun output_handle_mode(void *data, struct wl_output *wl_output, uint32_t flags,
108*4882a593Smuzhiyun int width, int height, int refresh)
109*4882a593Smuzhiyun {
110*4882a593Smuzhiyun struct xwl_output *xwl_output = data;
111*4882a593Smuzhiyun
112*4882a593Smuzhiyun if (!(flags & WL_OUTPUT_MODE_CURRENT))
113*4882a593Smuzhiyun return;
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* Apply the change from wl_output only if xdg-output is not supported */
116*4882a593Smuzhiyun if (!xwl_output->xdg_output) {
117*4882a593Smuzhiyun xwl_output->width = width;
118*4882a593Smuzhiyun xwl_output->height = height;
119*4882a593Smuzhiyun }
120*4882a593Smuzhiyun xwl_output->refresh = refresh;
121*4882a593Smuzhiyun }
122*4882a593Smuzhiyun
123*4882a593Smuzhiyun static inline void
output_get_new_size(struct xwl_output * xwl_output,Bool need_rotate,int * height,int * width)124*4882a593Smuzhiyun output_get_new_size(struct xwl_output *xwl_output,
125*4882a593Smuzhiyun Bool need_rotate,
126*4882a593Smuzhiyun int *height, int *width)
127*4882a593Smuzhiyun {
128*4882a593Smuzhiyun int output_width, output_height;
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun if (!need_rotate || (xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180))) {
131*4882a593Smuzhiyun output_width = xwl_output->width;
132*4882a593Smuzhiyun output_height = xwl_output->height;
133*4882a593Smuzhiyun } else {
134*4882a593Smuzhiyun output_width = xwl_output->height;
135*4882a593Smuzhiyun output_height = xwl_output->width;
136*4882a593Smuzhiyun }
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun if (*width < xwl_output->x + output_width)
139*4882a593Smuzhiyun *width = xwl_output->x + output_width;
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun if (*height < xwl_output->y + output_height)
142*4882a593Smuzhiyun *height = xwl_output->y + output_height;
143*4882a593Smuzhiyun }
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun static int
xwl_set_pixmap_visit_window(WindowPtr window,void * data)146*4882a593Smuzhiyun xwl_set_pixmap_visit_window(WindowPtr window, void *data)
147*4882a593Smuzhiyun {
148*4882a593Smuzhiyun ScreenPtr screen = window->drawable.pScreen;
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun if (screen->GetWindowPixmap(window) == data) {
151*4882a593Smuzhiyun screen->SetWindowPixmap(window, screen->GetScreenPixmap(screen));
152*4882a593Smuzhiyun return WT_WALKCHILDREN;
153*4882a593Smuzhiyun }
154*4882a593Smuzhiyun
155*4882a593Smuzhiyun return WT_DONTWALKCHILDREN;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun
158*4882a593Smuzhiyun static void
update_backing_pixmaps(struct xwl_screen * xwl_screen,int width,int height)159*4882a593Smuzhiyun update_backing_pixmaps(struct xwl_screen *xwl_screen, int width, int height)
160*4882a593Smuzhiyun {
161*4882a593Smuzhiyun ScreenPtr pScreen = xwl_screen->screen;
162*4882a593Smuzhiyun WindowPtr pRoot = pScreen->root;
163*4882a593Smuzhiyun PixmapPtr old_pixmap, new_pixmap;
164*4882a593Smuzhiyun
165*4882a593Smuzhiyun old_pixmap = pScreen->GetScreenPixmap(pScreen);
166*4882a593Smuzhiyun new_pixmap = pScreen->CreatePixmap(pScreen, width, height,
167*4882a593Smuzhiyun pScreen->rootDepth,
168*4882a593Smuzhiyun CREATE_PIXMAP_USAGE_BACKING_PIXMAP);
169*4882a593Smuzhiyun pScreen->SetScreenPixmap(new_pixmap);
170*4882a593Smuzhiyun
171*4882a593Smuzhiyun if (old_pixmap) {
172*4882a593Smuzhiyun TraverseTree(pRoot, xwl_set_pixmap_visit_window, old_pixmap);
173*4882a593Smuzhiyun pScreen->DestroyPixmap(old_pixmap);
174*4882a593Smuzhiyun }
175*4882a593Smuzhiyun
176*4882a593Smuzhiyun pScreen->ResizeWindow(pRoot, 0, 0, width, height, NULL);
177*4882a593Smuzhiyun }
178*4882a593Smuzhiyun
179*4882a593Smuzhiyun static void
update_screen_size(struct xwl_output * xwl_output,int width,int height)180*4882a593Smuzhiyun update_screen_size(struct xwl_output *xwl_output, int width, int height)
181*4882a593Smuzhiyun {
182*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
183*4882a593Smuzhiyun
184*4882a593Smuzhiyun if (xwl_screen->root_clip_mode == ROOT_CLIP_FULL)
185*4882a593Smuzhiyun SetRootClip(xwl_screen->screen, ROOT_CLIP_NONE);
186*4882a593Smuzhiyun
187*4882a593Smuzhiyun if (!xwl_screen->rootless && xwl_screen->screen->root)
188*4882a593Smuzhiyun update_backing_pixmaps (xwl_screen, width, height);
189*4882a593Smuzhiyun
190*4882a593Smuzhiyun xwl_screen->width = width;
191*4882a593Smuzhiyun xwl_screen->height = height;
192*4882a593Smuzhiyun xwl_screen->screen->width = width;
193*4882a593Smuzhiyun xwl_screen->screen->height = height;
194*4882a593Smuzhiyun xwl_screen->screen->mmWidth = (width * 25.4) / monitorResolution;
195*4882a593Smuzhiyun xwl_screen->screen->mmHeight = (height * 25.4) / monitorResolution;
196*4882a593Smuzhiyun
197*4882a593Smuzhiyun SetRootClip(xwl_screen->screen, xwl_screen->root_clip_mode);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun if (xwl_screen->screen->root) {
200*4882a593Smuzhiyun BoxRec box = { 0, 0, width, height };
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun xwl_screen->screen->root->drawable.width = width;
203*4882a593Smuzhiyun xwl_screen->screen->root->drawable.height = height;
204*4882a593Smuzhiyun RegionReset(&xwl_screen->screen->root->winSize, &box);
205*4882a593Smuzhiyun RRScreenSizeNotify(xwl_screen->screen);
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun update_desktop_dimensions();
209*4882a593Smuzhiyun }
210*4882a593Smuzhiyun
211*4882a593Smuzhiyun static void
apply_output_change(struct xwl_output * xwl_output)212*4882a593Smuzhiyun apply_output_change(struct xwl_output *xwl_output)
213*4882a593Smuzhiyun {
214*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
215*4882a593Smuzhiyun struct xwl_output *it;
216*4882a593Smuzhiyun int mode_width, mode_height;
217*4882a593Smuzhiyun int width = 0, height = 0, has_this_output = 0;
218*4882a593Smuzhiyun RRModePtr randr_mode;
219*4882a593Smuzhiyun Bool need_rotate;
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun /* Clear out the "done" received flags */
222*4882a593Smuzhiyun xwl_output->wl_output_done = FALSE;
223*4882a593Smuzhiyun xwl_output->xdg_output_done = FALSE;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun /* xdg-output sends output size in compositor space. so already rotated */
226*4882a593Smuzhiyun need_rotate = (xwl_output->xdg_output == NULL);
227*4882a593Smuzhiyun
228*4882a593Smuzhiyun /* We need to rotate back the logical size for the mode */
229*4882a593Smuzhiyun if (need_rotate || xwl_output->rotation & (RR_Rotate_0 | RR_Rotate_180)) {
230*4882a593Smuzhiyun mode_width = xwl_output->width;
231*4882a593Smuzhiyun mode_height = xwl_output->height;
232*4882a593Smuzhiyun } else {
233*4882a593Smuzhiyun mode_width = xwl_output->height;
234*4882a593Smuzhiyun mode_height = xwl_output->width;
235*4882a593Smuzhiyun }
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun randr_mode = xwayland_cvt(mode_width, mode_height,
238*4882a593Smuzhiyun xwl_output->refresh / 1000.0, 0, 0);
239*4882a593Smuzhiyun RROutputSetModes(xwl_output->randr_output, &randr_mode, 1, 1);
240*4882a593Smuzhiyun RRCrtcNotify(xwl_output->randr_crtc, randr_mode,
241*4882a593Smuzhiyun xwl_output->x, xwl_output->y,
242*4882a593Smuzhiyun xwl_output->rotation, NULL, 1, &xwl_output->randr_output);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun xorg_list_for_each_entry(it, &xwl_screen->output_list, link) {
245*4882a593Smuzhiyun /* output done event is sent even when some property
246*4882a593Smuzhiyun * of output is changed. That means that we may already
247*4882a593Smuzhiyun * have this output. If it is true, we must not add it
248*4882a593Smuzhiyun * into the output_list otherwise we'll corrupt it */
249*4882a593Smuzhiyun if (it == xwl_output)
250*4882a593Smuzhiyun has_this_output = 1;
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun output_get_new_size(it, need_rotate, &height, &width);
253*4882a593Smuzhiyun }
254*4882a593Smuzhiyun
255*4882a593Smuzhiyun if (!has_this_output) {
256*4882a593Smuzhiyun xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
257*4882a593Smuzhiyun
258*4882a593Smuzhiyun /* we did not check this output for new screen size, do it now */
259*4882a593Smuzhiyun output_get_new_size(xwl_output, need_rotate, &height, &width);
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun --xwl_screen->expecting_event;
262*4882a593Smuzhiyun }
263*4882a593Smuzhiyun
264*4882a593Smuzhiyun update_screen_size(xwl_output, width, height);
265*4882a593Smuzhiyun }
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun static void
output_handle_done(void * data,struct wl_output * wl_output)268*4882a593Smuzhiyun output_handle_done(void *data, struct wl_output *wl_output)
269*4882a593Smuzhiyun {
270*4882a593Smuzhiyun struct xwl_output *xwl_output = data;
271*4882a593Smuzhiyun
272*4882a593Smuzhiyun xwl_output->wl_output_done = TRUE;
273*4882a593Smuzhiyun /* Apply the changes from wl_output only if both "done" events are received,
274*4882a593Smuzhiyun * or if xdg-output is not supported.
275*4882a593Smuzhiyun */
276*4882a593Smuzhiyun if (xwl_output->xdg_output_done || !xwl_output->xdg_output)
277*4882a593Smuzhiyun apply_output_change(xwl_output);
278*4882a593Smuzhiyun }
279*4882a593Smuzhiyun
280*4882a593Smuzhiyun static void
output_handle_scale(void * data,struct wl_output * wl_output,int32_t factor)281*4882a593Smuzhiyun output_handle_scale(void *data, struct wl_output *wl_output, int32_t factor)
282*4882a593Smuzhiyun {
283*4882a593Smuzhiyun }
284*4882a593Smuzhiyun
285*4882a593Smuzhiyun static const struct wl_output_listener output_listener = {
286*4882a593Smuzhiyun output_handle_geometry,
287*4882a593Smuzhiyun output_handle_mode,
288*4882a593Smuzhiyun output_handle_done,
289*4882a593Smuzhiyun output_handle_scale
290*4882a593Smuzhiyun };
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun static void
xdg_output_handle_logical_position(void * data,struct zxdg_output_v1 * xdg_output,int32_t x,int32_t y)293*4882a593Smuzhiyun xdg_output_handle_logical_position(void *data, struct zxdg_output_v1 *xdg_output,
294*4882a593Smuzhiyun int32_t x, int32_t y)
295*4882a593Smuzhiyun {
296*4882a593Smuzhiyun struct xwl_output *xwl_output = data;
297*4882a593Smuzhiyun
298*4882a593Smuzhiyun xwl_output->x = x;
299*4882a593Smuzhiyun xwl_output->y = y;
300*4882a593Smuzhiyun }
301*4882a593Smuzhiyun
302*4882a593Smuzhiyun static void
xdg_output_handle_logical_size(void * data,struct zxdg_output_v1 * xdg_output,int32_t width,int32_t height)303*4882a593Smuzhiyun xdg_output_handle_logical_size(void *data, struct zxdg_output_v1 *xdg_output,
304*4882a593Smuzhiyun int32_t width, int32_t height)
305*4882a593Smuzhiyun {
306*4882a593Smuzhiyun struct xwl_output *xwl_output = data;
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun xwl_output->width = width;
309*4882a593Smuzhiyun xwl_output->height = height;
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun
312*4882a593Smuzhiyun static void
xdg_output_handle_done(void * data,struct zxdg_output_v1 * xdg_output)313*4882a593Smuzhiyun xdg_output_handle_done(void *data, struct zxdg_output_v1 *xdg_output)
314*4882a593Smuzhiyun {
315*4882a593Smuzhiyun struct xwl_output *xwl_output = data;
316*4882a593Smuzhiyun
317*4882a593Smuzhiyun xwl_output->xdg_output_done = TRUE;
318*4882a593Smuzhiyun if (xwl_output->wl_output_done)
319*4882a593Smuzhiyun apply_output_change(xwl_output);
320*4882a593Smuzhiyun }
321*4882a593Smuzhiyun
322*4882a593Smuzhiyun static const struct zxdg_output_v1_listener xdg_output_listener = {
323*4882a593Smuzhiyun xdg_output_handle_logical_position,
324*4882a593Smuzhiyun xdg_output_handle_logical_size,
325*4882a593Smuzhiyun xdg_output_handle_done,
326*4882a593Smuzhiyun };
327*4882a593Smuzhiyun
328*4882a593Smuzhiyun struct xwl_output *
xwl_output_create(struct xwl_screen * xwl_screen,uint32_t id)329*4882a593Smuzhiyun xwl_output_create(struct xwl_screen *xwl_screen, uint32_t id)
330*4882a593Smuzhiyun {
331*4882a593Smuzhiyun struct xwl_output *xwl_output;
332*4882a593Smuzhiyun static int serial;
333*4882a593Smuzhiyun char name[256];
334*4882a593Smuzhiyun
335*4882a593Smuzhiyun xwl_output = calloc(1, sizeof *xwl_output);
336*4882a593Smuzhiyun if (xwl_output == NULL) {
337*4882a593Smuzhiyun ErrorF("%s ENOMEM\n", __func__);
338*4882a593Smuzhiyun return NULL;
339*4882a593Smuzhiyun }
340*4882a593Smuzhiyun
341*4882a593Smuzhiyun xwl_output->output = wl_registry_bind(xwl_screen->registry, id,
342*4882a593Smuzhiyun &wl_output_interface, 2);
343*4882a593Smuzhiyun if (!xwl_output->output) {
344*4882a593Smuzhiyun ErrorF("Failed binding wl_output\n");
345*4882a593Smuzhiyun goto err;
346*4882a593Smuzhiyun }
347*4882a593Smuzhiyun
348*4882a593Smuzhiyun xwl_output->server_output_id = id;
349*4882a593Smuzhiyun wl_output_add_listener(xwl_output->output, &output_listener, xwl_output);
350*4882a593Smuzhiyun
351*4882a593Smuzhiyun snprintf(name, sizeof name, "XWAYLAND%d", serial++);
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun xwl_output->xwl_screen = xwl_screen;
354*4882a593Smuzhiyun xwl_output->randr_crtc = RRCrtcCreate(xwl_screen->screen, xwl_output);
355*4882a593Smuzhiyun if (!xwl_output->randr_crtc) {
356*4882a593Smuzhiyun ErrorF("Failed creating RandR CRTC\n");
357*4882a593Smuzhiyun goto err;
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun RRCrtcSetRotations (xwl_output->randr_crtc, ALL_ROTATIONS);
360*4882a593Smuzhiyun
361*4882a593Smuzhiyun xwl_output->randr_output = RROutputCreate(xwl_screen->screen, name,
362*4882a593Smuzhiyun strlen(name), xwl_output);
363*4882a593Smuzhiyun if (!xwl_output->randr_output) {
364*4882a593Smuzhiyun ErrorF("Failed creating RandR Output\n");
365*4882a593Smuzhiyun goto err;
366*4882a593Smuzhiyun }
367*4882a593Smuzhiyun
368*4882a593Smuzhiyun RRCrtcGammaSetSize(xwl_output->randr_crtc, 256);
369*4882a593Smuzhiyun RROutputSetCrtcs(xwl_output->randr_output, &xwl_output->randr_crtc, 1);
370*4882a593Smuzhiyun RROutputSetConnection(xwl_output->randr_output, RR_Connected);
371*4882a593Smuzhiyun
372*4882a593Smuzhiyun /* We want the output to be in the list as soon as created so we can
373*4882a593Smuzhiyun * use it when binding to the xdg-output protocol...
374*4882a593Smuzhiyun */
375*4882a593Smuzhiyun xorg_list_append(&xwl_output->link, &xwl_screen->output_list);
376*4882a593Smuzhiyun --xwl_screen->expecting_event;
377*4882a593Smuzhiyun
378*4882a593Smuzhiyun if (xwl_screen->xdg_output_manager)
379*4882a593Smuzhiyun xwl_output_get_xdg_output(xwl_output);
380*4882a593Smuzhiyun
381*4882a593Smuzhiyun return xwl_output;
382*4882a593Smuzhiyun
383*4882a593Smuzhiyun err:
384*4882a593Smuzhiyun if (xwl_output->randr_crtc)
385*4882a593Smuzhiyun RRCrtcDestroy(xwl_output->randr_crtc);
386*4882a593Smuzhiyun if (xwl_output->output)
387*4882a593Smuzhiyun wl_output_destroy(xwl_output->output);
388*4882a593Smuzhiyun free(xwl_output);
389*4882a593Smuzhiyun return NULL;
390*4882a593Smuzhiyun }
391*4882a593Smuzhiyun
392*4882a593Smuzhiyun void
xwl_output_destroy(struct xwl_output * xwl_output)393*4882a593Smuzhiyun xwl_output_destroy(struct xwl_output *xwl_output)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun wl_output_destroy(xwl_output->output);
396*4882a593Smuzhiyun free(xwl_output);
397*4882a593Smuzhiyun }
398*4882a593Smuzhiyun
399*4882a593Smuzhiyun void
xwl_output_remove(struct xwl_output * xwl_output)400*4882a593Smuzhiyun xwl_output_remove(struct xwl_output *xwl_output)
401*4882a593Smuzhiyun {
402*4882a593Smuzhiyun struct xwl_output *it;
403*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
404*4882a593Smuzhiyun int width = 0, height = 0;
405*4882a593Smuzhiyun Bool need_rotate = (xwl_output->xdg_output == NULL);
406*4882a593Smuzhiyun
407*4882a593Smuzhiyun xorg_list_del(&xwl_output->link);
408*4882a593Smuzhiyun
409*4882a593Smuzhiyun xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
410*4882a593Smuzhiyun output_get_new_size(it, need_rotate, &height, &width);
411*4882a593Smuzhiyun update_screen_size(xwl_output, width, height);
412*4882a593Smuzhiyun
413*4882a593Smuzhiyun RRCrtcDestroy(xwl_output->randr_crtc);
414*4882a593Smuzhiyun RROutputDestroy(xwl_output->randr_output);
415*4882a593Smuzhiyun
416*4882a593Smuzhiyun xwl_output_destroy(xwl_output);
417*4882a593Smuzhiyun }
418*4882a593Smuzhiyun
419*4882a593Smuzhiyun static Bool
xwl_randr_get_info(ScreenPtr pScreen,Rotation * rotations)420*4882a593Smuzhiyun xwl_randr_get_info(ScreenPtr pScreen, Rotation * rotations)
421*4882a593Smuzhiyun {
422*4882a593Smuzhiyun *rotations = ALL_ROTATIONS;
423*4882a593Smuzhiyun
424*4882a593Smuzhiyun return TRUE;
425*4882a593Smuzhiyun }
426*4882a593Smuzhiyun
427*4882a593Smuzhiyun static Bool
xwl_randr_set_config(ScreenPtr pScreen,Rotation rotation,int rate,RRScreenSizePtr pSize)428*4882a593Smuzhiyun xwl_randr_set_config(ScreenPtr pScreen,
429*4882a593Smuzhiyun Rotation rotation, int rate, RRScreenSizePtr pSize)
430*4882a593Smuzhiyun {
431*4882a593Smuzhiyun return FALSE;
432*4882a593Smuzhiyun }
433*4882a593Smuzhiyun
434*4882a593Smuzhiyun Bool
xwl_screen_init_output(struct xwl_screen * xwl_screen)435*4882a593Smuzhiyun xwl_screen_init_output(struct xwl_screen *xwl_screen)
436*4882a593Smuzhiyun {
437*4882a593Smuzhiyun rrScrPrivPtr rp;
438*4882a593Smuzhiyun
439*4882a593Smuzhiyun if (!RRScreenInit(xwl_screen->screen))
440*4882a593Smuzhiyun return FALSE;
441*4882a593Smuzhiyun
442*4882a593Smuzhiyun RRScreenSetSizeRange(xwl_screen->screen, 16, 16, 32767, 32767);
443*4882a593Smuzhiyun
444*4882a593Smuzhiyun rp = rrGetScrPriv(xwl_screen->screen);
445*4882a593Smuzhiyun rp->rrGetInfo = xwl_randr_get_info;
446*4882a593Smuzhiyun rp->rrSetConfig = xwl_randr_set_config;
447*4882a593Smuzhiyun
448*4882a593Smuzhiyun return TRUE;
449*4882a593Smuzhiyun }
450*4882a593Smuzhiyun
451*4882a593Smuzhiyun static void
xwl_output_get_xdg_output(struct xwl_output * xwl_output)452*4882a593Smuzhiyun xwl_output_get_xdg_output(struct xwl_output *xwl_output)
453*4882a593Smuzhiyun {
454*4882a593Smuzhiyun struct xwl_screen *xwl_screen = xwl_output->xwl_screen;
455*4882a593Smuzhiyun
456*4882a593Smuzhiyun xwl_output->xdg_output =
457*4882a593Smuzhiyun zxdg_output_manager_v1_get_xdg_output (xwl_screen->xdg_output_manager,
458*4882a593Smuzhiyun xwl_output->output);
459*4882a593Smuzhiyun
460*4882a593Smuzhiyun zxdg_output_v1_add_listener(xwl_output->xdg_output,
461*4882a593Smuzhiyun &xdg_output_listener,
462*4882a593Smuzhiyun xwl_output);
463*4882a593Smuzhiyun }
464*4882a593Smuzhiyun
465*4882a593Smuzhiyun void
xwl_screen_init_xdg_output(struct xwl_screen * xwl_screen)466*4882a593Smuzhiyun xwl_screen_init_xdg_output(struct xwl_screen *xwl_screen)
467*4882a593Smuzhiyun {
468*4882a593Smuzhiyun struct xwl_output *it;
469*4882a593Smuzhiyun
470*4882a593Smuzhiyun assert(xwl_screen->xdg_output_manager);
471*4882a593Smuzhiyun
472*4882a593Smuzhiyun xorg_list_for_each_entry(it, &xwl_screen->output_list, link)
473*4882a593Smuzhiyun xwl_output_get_xdg_output(it);
474*4882a593Smuzhiyun }
475