chiark / gitweb /
Imported Upstream version 1.0.0
[e16] / src / zoom.c
1 /*
2  * Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
3  * Copyright (C) 2004-2008 Kim Woelders
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a copy
6  * of this software and associated documentation files (the "Software"), to
7  * deal in the Software without restriction, including without limitation the
8  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9  * sell copies of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be included in
13  * all copies of the Software, its documentation and marketing & publicity
14  * materials, and acknowledgment shall be given in the documentation, materials
15  * and software packages that this Software was used.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
20  * THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
21  * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
22  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23  */
24 #include "E.h"
25 #include "ewins.h"
26 #include "focus.h"
27 #include "xwin.h"
28
29 #ifdef WITH_ZOOM
30 #include <X11/extensions/xf86vmode.h>
31
32 static int          std_vid_modes_num = 0;
33 static int          std_vid_mode_cur = 0;
34 static XF86VidModeModeInfo **std_vid_modes = NULL;
35
36 static Win          zoom_mask_1 = 0;
37 static Win          zoom_mask_2 = 0;
38 static Win          zoom_mask_3 = 0;
39 static Win          zoom_mask_4 = 0;
40 static EWin        *zoom_last_ewin = NULL;
41 static int          zoom_last_x, zoom_last_y;
42 static char         zoom_can = 0;
43
44 static void
45 FillStdVidModes(void)
46 {
47    XF86VidModeGetAllModeLines(disp, Dpy.screen,
48                               &std_vid_modes_num, &std_vid_modes);
49 }
50
51 static XF86VidModeModeInfo *
52 FindMode(int w, int h)
53 {
54    XF86VidModeModeInfo *chosen = NULL;
55    int                 i, closest = 0x7fffffff;
56
57    for (i = 0; i < std_vid_modes_num; i++)
58      {
59         int                 value = 0x7fffffff;
60
61         if ((std_vid_modes[i]->hdisplay >= w) &&
62             (std_vid_modes[i]->vdisplay >= h))
63            value = ((std_vid_modes[i]->hdisplay - w) +
64                     (std_vid_modes[i]->vdisplay - h));
65         if (value < closest)
66           {
67              closest = value;
68              chosen = std_vid_modes[i];
69           }
70      }
71    return chosen;
72 }
73
74 static int
75 GetModeIndex(unsigned int dotclock, XF86VidModeModeLine * line)
76 {
77    int                 i;
78    const XF86VidModeModeInfo *info;
79
80    for (i = 0; i < std_vid_modes_num; i++)
81      {
82         info = std_vid_modes[i];
83         if (info->dotclock == dotclock &&
84             info->hdisplay == line->hdisplay &&
85             info->vdisplay == line->vdisplay)
86            return i;
87      }
88    return 0;
89 }
90
91 static const XF86VidModeModeInfo *
92 SwitchRes(char inout, int x, int y, int w, int h)
93 {
94    static int          vp_x, vp_y;
95    XF86VidModeModeInfo *mode = NULL;
96    int                 scr;
97
98    scr = Dpy.screen;
99
100    if (inout)
101      {
102         XF86VidModeModeLine curmode;
103         int                 dotclock;
104
105         if (!XF86VidModeGetModeLine(disp, scr, &dotclock, &curmode))
106            return mode;
107         XF86VidModeGetViewPort(disp, scr, &vp_x, &vp_y);
108
109         mode = FindMode(w, h);
110         if (mode)
111           {
112              XF86VidModeLockModeSwitch(disp, scr, 0);
113              std_vid_mode_cur = GetModeIndex(dotclock, &curmode);
114              XF86VidModeSwitchToMode(disp, scr, mode);
115              XF86VidModeSetViewPort(disp, scr, x, y);
116              XF86VidModeLockModeSwitch(disp, scr, 1);
117           }
118      }
119    else
120      {
121         mode = std_vid_modes[std_vid_mode_cur];
122         XF86VidModeLockModeSwitch(disp, scr, 0);
123         XF86VidModeSwitchToMode(disp, scr, mode);
124         XF86VidModeSetViewPort(disp, scr, vp_x, vp_y);
125 #if 0                           /* No, don't lock or we can't switch resolution */
126         XF86VidModeLockModeSwitch(disp, scr, 1);
127 #endif
128      }
129    return mode;
130 }
131
132 static char
133 XHasDGA(void)
134 {
135    int                 ev_base, er_base;
136
137    if (XF86VidModeQueryExtension(disp, &ev_base, &er_base))
138       return 1;
139    else
140       return 0;
141 }
142
143 EWin               *
144 GetZoomEWin(void)
145 {
146    return zoom_last_ewin;
147 }
148
149 void
150 ReZoom(EWin * ewin)
151 {
152    if ((InZoom()) && (ewin != zoom_last_ewin))
153      {
154         Zoom(NULL);
155         Zoom(ewin);
156      }
157 }
158
159 char
160 InZoom(void)
161 {
162    if (zoom_last_ewin)
163       return 1;
164    return 0;
165 }
166
167 char
168 CanZoom(void)
169 {
170    return zoom_can;
171 }
172
173 void
174 ZoomInit(void)
175 {
176    if (XHasDGA())
177      {
178         FillStdVidModes();
179         if (std_vid_modes_num > 1)
180            zoom_can = 1;
181      }
182 }
183
184 static              Win
185 ZoomMask(int x, int y, int w, int h)
186 {
187    Win                 win;
188
189    if (x < 0 || y < 0 || w <= 0 || h <= 0)
190       return 0;
191
192    win = ECreateWindow(VROOT, x, y, w, h, 0);
193    ESetWindowBackground(win, Dpy.pixel_black);
194    ERaiseWindow(win);
195    EMapWindow(win);
196
197    return win;
198 }
199
200 void
201 Zoom(EWin * ewin)
202 {
203    const XF86VidModeModeInfo *mode;
204
205    if (!CanZoom())
206       return;
207
208    if (!ewin)
209      {
210         if (zoom_last_ewin)
211           {
212              ewin = zoom_last_ewin;
213 /*           XUngrabPointer(disp, CurrentTime); */
214              EwinMove(ewin, zoom_last_x, zoom_last_y);
215              if (zoom_mask_1)
216                 EDestroyWindow(zoom_mask_1);
217              if (zoom_mask_2)
218                 EDestroyWindow(zoom_mask_2);
219              if (zoom_mask_3)
220                 EDestroyWindow(zoom_mask_3);
221              if (zoom_mask_4)
222                 EDestroyWindow(zoom_mask_4);
223              SwitchRes(0, 0, 0, 0, 0);
224              EwinWarpTo(ewin);
225              ESync(0);
226              zoom_last_ewin = NULL;
227           }
228         return;
229      }
230
231    mode = SwitchRes(1, 0, 0, ewin->client.w, ewin->client.h);
232    if (mode)
233      {
234         int                 x1, y1, x2, y2, bl, br, bt, bb;
235
236         zoom_last_ewin = ewin;
237         zoom_last_x = EoGetX(ewin);
238         zoom_last_y = EoGetY(ewin);
239         x1 = (mode->hdisplay - ewin->client.w) / 2;
240         if (x1 < 0)
241            x1 = 0;
242         y1 = (mode->vdisplay - ewin->client.h) / 2;
243         if (y1 < 0)
244            y1 = 0;
245         x2 = mode->hdisplay - ewin->client.w - x1;
246         if (x2 < 0)
247            x2 = 0;
248         y2 = mode->vdisplay - ewin->client.h - y1;
249         if (y2 < 0)
250            y2 = 0;
251         EwinRaise(ewin);
252         EwinBorderGetSize(ewin, &bl, &br, &bt, &bb);
253         EwinMove(ewin, -bl + x1, -bt + y1);
254         FocusToEWin(ewin, FOCUS_SET);
255         EwinWarpTo(ewin);
256 #if 0                           /* Doesn't work as intended */
257         XGrabPointer(disp, EwinGetClientXwin(ewin), True,
258                      ButtonPressMask | ButtonReleaseMask |
259                      PointerMotionMask | ButtonMotionMask |
260                      EnterWindowMask | LeaveWindowMask,
261                      GrabModeAsync, GrabModeAsync,
262                      EwinGetClientXwin(ewin), None, CurrentTime);
263 #endif
264         zoom_mask_1 = ZoomMask(0, 0, x1, mode->vdisplay);
265         zoom_mask_2 = ZoomMask(0, 0, mode->hdisplay, y1);
266         zoom_mask_3 = ZoomMask(x1 + ewin->client.w, 0, x2, mode->vdisplay);
267         zoom_mask_4 = ZoomMask(0, y1 + ewin->client.h, mode->hdisplay, y2);
268         ESync(0);
269      }
270 }
271
272 #else
273
274 EWin               *
275 GetZoomEWin(void)
276 {
277    return NULL;
278 }
279
280 void
281 ReZoom(EWin * ewin)
282 {
283    ewin = NULL;
284 }
285
286 char
287 InZoom(void)
288 {
289    return 0;
290 }
291
292 char
293 CanZoom(void)
294 {
295    return 0;
296 }
297
298 void
299 ZoomInit(void)
300 {
301 }
302
303 void
304 Zoom(EWin * ewin)
305 {
306    ewin = NULL;
307 }
308
309 #endif