]>
diplodocus.org Git - xorg-xinput/blob - src/transform.c
15fda590024f9f68226a3dd0ea97230986ff839e
2 * Copyright © 2011 Red Hat, Inc.
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:
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
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.
28 #include <X11/extensions/Xrandr.h>
29 #include <X11/extensions/Xinerama.h>
32 typedef struct Matrix
{
36 static void matrix_set(Matrix
*m
, int row
, int col
, float val
)
38 m
->m
[row
* 3 + col
] = val
;
41 static void matrix_set_unity(Matrix
*m
)
43 memset(m
, 0, sizeof(m
->m
));
44 matrix_set(m
, 0, 0, 1);
45 matrix_set(m
, 1, 1, 1);
46 matrix_set(m
, 2, 2, 1);
50 static void matrix_print(const Matrix
*m
)
52 printf("[ %3.3f %3.3f %3.3f ]\n", m
->m
[0], m
->m
[1], m
->m
[2]);
53 printf("[ %3.3f %3.3f %3.3f ]\n", m
->m
[3], m
->m
[4], m
->m
[5]);
54 printf("[ %3.3f %3.3f %3.3f ]\n", m
->m
[6], m
->m
[7], m
->m
[8]);
59 apply_matrix(Display
*dpy
, int deviceid
, Matrix
*m
)
61 Atom prop_float
, prop_matrix
;
70 unsigned long bytes_after
;
74 prop_float
= XInternAtom(dpy
, "FLOAT", False
);
75 prop_matrix
= XInternAtom(dpy
, "Coordinate Transformation Matrix", False
);
79 fprintf(stderr
, "Float atom not found. This server is too old.\n");
84 fprintf(stderr
, "Coordinate transformation matrix not found. This "
85 "server is too old\n");
89 rc
= XIGetProperty(dpy
, deviceid
, prop_matrix
, 0, 9, False
, prop_float
,
90 &type_return
, &format_return
, &nitems
, &bytes_after
,
92 if (rc
!= Success
|| prop_float
!= type_return
|| format_return
!= 32 ||
93 nitems
!= 9 || bytes_after
!= 0)
95 fprintf(stderr
, "Failed to retrieve current property values\n");
99 memcpy(data
.f
, m
->m
, sizeof(m
->m
));
101 XIChangeProperty(dpy
, deviceid
, prop_matrix
, prop_float
,
102 format_return
, PropModeReplace
, data
.c
, nitems
);
110 set_transformation_matrix(Display
*dpy
, Matrix
*m
, int offset_x
, int offset_y
,
111 int screen_width
, int screen_height
)
114 int width
= DisplayWidth(dpy
, DefaultScreen(dpy
));
115 int height
= DisplayHeight(dpy
, DefaultScreen(dpy
));
118 float x
= 1.0 * offset_x
/width
;
119 float y
= 1.0 * offset_y
/height
;
122 float w
= 1.0 * screen_width
/width
;
123 float h
= 1.0 * screen_height
/height
;
127 matrix_set(m
, 0, 2, x
);
128 matrix_set(m
, 1, 2, y
);
130 matrix_set(m
, 0, 0, w
);
131 matrix_set(m
, 1, 1, h
);
138 /* Caller must free return value */
139 static XRROutputInfo
*
140 find_output_xrandr(Display
*dpy
, const char *output_name
)
142 XRRScreenResources
*res
;
143 XRROutputInfo
*output_info
= NULL
;
147 res
= XRRGetScreenResources(dpy
, DefaultRootWindow(dpy
));
149 for (i
= 0; i
< res
->noutput
&& !found
; i
++)
151 output_info
= XRRGetOutputInfo(dpy
, res
, res
->outputs
[i
]);
153 if (output_info
->crtc
&& output_info
->connection
== RR_Connected
&&
154 strcmp(output_info
->name
, output_name
) == 0)
160 XRRFreeOutputInfo(output_info
);
163 XRRFreeScreenResources(res
);
172 map_output_xrandr(Display
*dpy
, int deviceid
, const char *output_name
)
174 int rc
= EXIT_FAILURE
;
175 XRRScreenResources
*res
;
176 XRROutputInfo
*output_info
;
178 res
= XRRGetScreenResources(dpy
, DefaultRootWindow(dpy
));
179 output_info
= find_output_xrandr(dpy
, output_name
);
181 /* crtc holds our screen info, need to compare to actual screen size */
184 XRRCrtcInfo
*crtc_info
;
186 matrix_set_unity(&m
);
187 crtc_info
= XRRGetCrtcInfo (dpy
, res
, output_info
->crtc
);
188 set_transformation_matrix(dpy
, &m
, crtc_info
->x
, crtc_info
->y
,
189 crtc_info
->width
, crtc_info
->height
);
190 rc
= apply_matrix(dpy
, deviceid
, &m
);
191 XRRFreeCrtcInfo(crtc_info
);
192 XRRFreeOutputInfo(output_info
);
194 printf("Unable to find output '%s'. "
195 "Output may not be connected.\n", output_name
);
197 XRRFreeScreenResources(res
);
203 map_output_xinerama(Display
*dpy
, int deviceid
, const char *output_name
)
205 const char *prefix
= "HEAD-";
206 XineramaScreenInfo
*screens
= NULL
;
207 int rc
= EXIT_FAILURE
;
213 if (!XineramaQueryExtension(dpy
, &event
, &error
))
215 fprintf(stderr
, "Unable to set screen mapping. Xinerama extension not found\n");
219 if (strlen(output_name
) < strlen(prefix
) + 1 ||
220 strncmp(output_name
, prefix
, strlen(prefix
)) != 0)
222 fprintf(stderr
, "Please specify the output name as HEAD-X,"
223 "where X is the screen number\n");
227 head
= output_name
[strlen(prefix
)] - '0';
229 screens
= XineramaQueryScreens(dpy
, &nscreens
);
233 fprintf(stderr
, "Xinerama failed to query screens.\n");
235 } else if (nscreens
<= head
)
237 fprintf(stderr
, "Found %d screens, but you requested %s.\n",
238 nscreens
, output_name
);
242 matrix_set_unity(&m
);
243 set_transformation_matrix(dpy
, &m
,
244 screens
[head
].x_org
, screens
[head
].y_org
,
245 screens
[head
].width
, screens
[head
].height
);
246 rc
= apply_matrix(dpy
, deviceid
, &m
);
254 map_to_output(Display
*dpy
, int argc
, char *argv
[], char *name
, char *desc
)
256 int opcode
, event
, error
;
263 fprintf(stderr
, "Usage: xinput %s %s\n", name
, desc
);
267 info
= xi2_find_device_info(dpy
, argv
[0]);
270 fprintf(stderr
, "unable to find device '%s'\n", argv
[0]);
274 output_name
= argv
[1];
276 /* Check for RandR 1.2. Server bug causes the NVIDIA driver to
277 * report with RandR 1.3 support but it doesn't expose RandR outputs.
278 * Force Xinerama if NV-CONTROL is present */
279 if (XQueryExtension(dpy
, "NV-CONTROL", &opcode
, &event
, &error
) ||
280 !XQueryExtension(dpy
, "RANDR", &opcode
, &event
, &error
) ||
281 !XRRQueryVersion(dpy
, &maj
, &min
) || (maj
* 1000 + min
) < 1002)
282 return map_output_xinerama(dpy
, info
->deviceid
, output_name
);
284 return map_output_xrandr(dpy
, info
->deviceid
, output_name
);