1 /*
2 * Copyright © 2013 Intel Corporation
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 DEALINGS
21 * IN THE SOFTWARE.
22 *
23 */
24
25 #include "config.h"
26
27 #include <X11/Xlib.h>
28 #ifdef HAVE_XRANDR
29 #include <X11/extensions/Xrandr.h>
30 #endif
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34
35 #include "position.h"
36 #include "../overlay.h"
37
get_position(struct config * config)38 static enum position get_position(struct config *config)
39 {
40 const char *v = config_get_value(config, "window", "position");
41 if (v == NULL)
42 return POS_UNSET;
43
44 if (strcmp(v, "top-left") == 0)
45 return POS_TOP_LEFT;
46
47 if (strcmp(v, "top-centre") == 0)
48 return POS_TOP_CENTRE;
49
50 if (strcmp(v, "top-right") == 0)
51 return POS_TOP_RIGHT;
52
53 if (strcmp(v, "middle-left") == 0)
54 return POS_MIDDLE_LEFT;
55
56 if (strcmp(v, "middle-centre") == 0)
57 return POS_MIDDLE_CENTRE;
58
59 if (strcmp(v, "middle-right") == 0)
60 return POS_MIDDLE_RIGHT;
61
62 if (strcmp(v, "bottom-left") == 0)
63 return POS_BOTTOM_LEFT;
64
65 if (strcmp(v, "bottom-centre") == 0)
66 return POS_BOTTOM_CENTRE;
67
68 if (strcmp(v, "bottom-right") == 0)
69 return POS_BOTTOM_RIGHT;
70
71 return POS_UNSET;
72 }
73
screen_size(Display * dpy,struct config * config,int * scr_x,int * scr_y,int * scr_width,int * scr_height)74 static void screen_size(Display *dpy, struct config *config,
75 int *scr_x, int *scr_y, int *scr_width, int *scr_height)
76 {
77 Screen *scr;
78
79 #ifdef HAVE_XRANDR
80 const char *crtc;
81
82 crtc = config_get_value(config, "x11", "crtc");
83 if (crtc) {
84 XRRScreenResources *res;
85 int i = atoi(crtc);
86 int ok = 0;
87
88 res = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
89 if (res) {
90 if (i < res->ncrtc) {
91 XRRCrtcInfo *info = XRRGetCrtcInfo (dpy, res, res->crtcs[i]);
92 if (info) {
93 *scr_x = info->x;
94 *scr_y = info->y;
95 *scr_width = info->width;
96 *scr_height = info->height;
97 ok = 1;
98 XRRFreeCrtcInfo(info);
99 }
100 }
101 XRRFreeScreenResources(res);
102 }
103 if (ok)
104 return;
105 }
106 #endif
107
108 scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
109 *scr_x = *scr_y = 0;
110 *scr_width = scr->width;
111 *scr_height = scr->height;
112 }
113
114 enum position
x11_position(Display * dpy,int width,int height,struct config * config,int * x,int * y,int * w,int * h)115 x11_position(Display *dpy, int width, int height,
116 struct config *config,
117 int *x, int *y, int *w, int *h)
118 {
119 enum position position = POS_UNSET;
120 const char *geometry;
121
122 *x = *y = 0;
123 *w = width;
124 *h = height;
125
126 geometry = config_get_value(config, "window", "geometry");
127 if (geometry) {
128 sscanf(geometry, "%dx%d+%d+%d", w, h, x, y);
129 if (*w < width/2)
130 *w = width/2;
131 if (*h < height/2)
132 *h = height/2;
133 } else {
134 int scr_x, scr_y, scr_width, scr_height;
135
136 screen_size(dpy, config, &scr_x, &scr_y, &scr_width, &scr_height);
137 position = get_position(config);
138
139 if (position != POS_UNSET) {
140 if (width == -1) {
141 *w = scr_width;
142 switch (position & 7) {
143 default:
144 case 0:
145 case 2: *w >>= 1; break;
146 }
147 }
148
149 if (height == -1) {
150 *h = scr_height;
151 switch ((position >> 4) & 7) {
152 default:
153 case 0:
154 case 2: *h >>= 1; break;
155 }
156 }
157 }
158
159 geometry = config_get_value(config, "window", "size");
160 if (geometry) {
161 int size_w, size_h;
162 float scale_x, scale_y;
163
164 if (sscanf(geometry, "%dx%d", &size_w, &size_h) == 2) {
165 *w = size_w;
166 *h = size_h;
167 } else if (sscanf(geometry, "%f%%x%f%%", &scale_x, &scale_y) == 2) {
168 if (*w != -1)
169 *w = (*w * scale_x) / 100.;
170 if (*h != -1)
171 *h = (*h * scale_y) / 100.;
172 } else if (sscanf(geometry, "%f%%", &scale_x) == 1) {
173 if (*w != -1)
174 *w = (*w * scale_x) / 100.;
175 if (*h != -1)
176 *h = (*h * scale_x) / 100.;
177 }
178 if ((unsigned)*w < width/2)
179 *w = width/2;
180 if ((unsigned)*h < height/2)
181 *h = height/2;
182 }
183
184 if ((unsigned)*w > scr_width)
185 *w = scr_width;
186
187 if ((unsigned)*h > scr_height)
188 *h = scr_height;
189
190 if (position != POS_UNSET) {
191 switch (position & 7) {
192 default:
193 case 0: *x = 0; break;
194 case 1: *x = (scr_width - *w)/2; break;
195 case 2: *x = scr_width - *w; break;
196 }
197
198 switch ((position >> 4) & 7) {
199 default:
200 case 0: *y = 0; break;
201 case 1: *y = (scr_height - *h)/2; break;
202 case 2: *y = scr_height - *h; break;
203 }
204 }
205
206 *x += scr_x;
207 *y += scr_y;
208 }
209
210 return position;
211 }
212