]>
diplodocus.org Git - xorg-xinput/blob - src/transform.c
3ea7ff85e98cc213d87134213aeabeae15a2e2b7
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
);
139 map_output_xrandr(Display
*dpy
, int deviceid
, const char *output_name
)
142 int rc
= EXIT_FAILURE
;
143 XRRScreenResources
*res
;
144 XRROutputInfo
*output_info
;
146 res
= XRRGetScreenResources(dpy
, DefaultRootWindow(dpy
));
148 for (i
= 0; i
< res
->noutput
&& !found
; i
++)
150 output_info
= XRRGetOutputInfo(dpy
, res
, res
->outputs
[i
]);
152 if (output_info
->crtc
&& output_info
->connection
== RR_Connected
&&
153 strcmp(output_info
->name
, output_name
) == 0)
159 XRRFreeOutputInfo(output_info
);
162 /* crtc holds our screen info, need to compare to actual screen size */
165 XRRCrtcInfo
*crtc_info
;
167 matrix_set_unity(&m
);
168 crtc_info
= XRRGetCrtcInfo (dpy
, res
, output_info
->crtc
);
169 set_transformation_matrix(dpy
, &m
, crtc_info
->x
, crtc_info
->y
,
170 crtc_info
->width
, crtc_info
->height
);
171 rc
= apply_matrix(dpy
, deviceid
, &m
);
172 XRRFreeCrtcInfo(crtc_info
);
173 XRRFreeOutputInfo(output_info
);
175 printf("Unable to find output '%s'. "
176 "Output may not be connected.\n", output_name
);
178 XRRFreeScreenResources(res
);
184 map_output_xinerama(Display
*dpy
, int deviceid
, const char *output_name
)
186 const char *prefix
= "HEAD-";
187 XineramaScreenInfo
*screens
= NULL
;
188 int rc
= EXIT_FAILURE
;
194 if (!XineramaQueryExtension(dpy
, &event
, &error
))
196 fprintf(stderr
, "Unable to set screen mapping. Xinerama extension not found\n");
200 if (strlen(output_name
) < strlen(prefix
) + 1 ||
201 strncmp(output_name
, prefix
, strlen(prefix
)) != 0)
203 fprintf(stderr
, "Please specify the output name as HEAD-X,"
204 "where X is the screen number\n");
208 head
= output_name
[strlen(prefix
)] - '0';
210 screens
= XineramaQueryScreens(dpy
, &nscreens
);
214 fprintf(stderr
, "Xinerama failed to query screens.\n");
216 } else if (nscreens
<= head
)
218 fprintf(stderr
, "Found %d screens, but you requested %s.\n",
219 nscreens
, output_name
);
223 matrix_set_unity(&m
);
224 set_transformation_matrix(dpy
, &m
,
225 screens
[head
].x_org
, screens
[head
].y_org
,
226 screens
[head
].width
, screens
[head
].height
);
227 rc
= apply_matrix(dpy
, deviceid
, &m
);
235 map_to_output(Display
*dpy
, int argc
, char *argv
[], char *name
, char *desc
)
237 int opcode
, event
, error
;
244 fprintf(stderr
, "Usage: xinput %s %s\n", name
, desc
);
248 info
= xi2_find_device_info(dpy
, argv
[0]);
251 fprintf(stderr
, "unable to find device '%s'\n", argv
[0]);
255 output_name
= argv
[1];
257 /* Check for RandR 1.2. Server bug causes the NVIDIA driver to
258 * report with RandR 1.3 support but it doesn't expose RandR outputs.
259 * Force Xinerama if NV-CONTROL is present */
260 if (XQueryExtension(dpy
, "NV-CONTROL", &opcode
, &event
, &error
) ||
261 !XQueryExtension(dpy
, "RANDR", &opcode
, &event
, &error
) ||
262 !XRRQueryVersion(dpy
, &maj
, &min
) || (maj
* 1000 + min
) < 1002)
263 return map_output_xinerama(dpy
, info
->deviceid
, output_name
);
265 return map_output_xrandr(dpy
, info
->deviceid
, output_name
);