e16/src/zoom.c

298 lines
6.7 KiB
C

/*
* Copyright (C) 2000-2007 Carsten Haitzler, Geoff Harrison and various contributors
* Copyright (C) 2004-2009 Kim Woelders
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies of the Software, its documentation and marketing & publicity
* materials, and acknowledgment shall be given in the documentation, materials
* and software packages that this Software was used.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "E.h"
#include "ewins.h"
#include "focus.h"
#include "xwin.h"
#ifdef WITH_ZOOM
#include <X11/extensions/xf86vmode.h>
static int std_vid_modes_num = 0;
static int std_vid_mode_cur = 0;
static XF86VidModeModeInfo **std_vid_modes = NULL;
static Win zoom_mask_1 = 0;
static Win zoom_mask_2 = 0;
static Win zoom_mask_3 = 0;
static Win zoom_mask_4 = 0;
static EWin *zoom_last_ewin = NULL;
static int zoom_last_x, zoom_last_y;
static char zoom_can = 0;
static void
FillStdVidModes(void)
{
XF86VidModeGetAllModeLines(disp, Dpy.screen,
&std_vid_modes_num, &std_vid_modes);
}
static XF86VidModeModeInfo *
FindMode(int w, int h)
{
XF86VidModeModeInfo *chosen = NULL;
int i, closest = 0x7fffffff;
for (i = 0; i < std_vid_modes_num; i++)
{
int value = 0x7fffffff;
if ((std_vid_modes[i]->hdisplay >= w) &&
(std_vid_modes[i]->vdisplay >= h))
value = ((std_vid_modes[i]->hdisplay - w) +
(std_vid_modes[i]->vdisplay - h));
if (value < closest)
{
closest = value;
chosen = std_vid_modes[i];
}
}
return chosen;
}
static int
GetModeIndex(unsigned int dotclock, XF86VidModeModeLine * line)
{
int i;
const XF86VidModeModeInfo *info;
for (i = 0; i < std_vid_modes_num; i++)
{
info = std_vid_modes[i];
if (info->dotclock == dotclock &&
info->hdisplay == line->hdisplay &&
info->vdisplay == line->vdisplay)
return i;
}
return 0;
}
static const XF86VidModeModeInfo *
SwitchRes(char inout, int x, int y, int w, int h)
{
static int vp_x, vp_y;
XF86VidModeModeInfo *mode = NULL;
int scr;
scr = Dpy.screen;
if (inout)
{
XF86VidModeModeLine curmode;
int dotclock;
if (!XF86VidModeGetModeLine(disp, scr, &dotclock, &curmode))
return mode;
XF86VidModeGetViewPort(disp, scr, &vp_x, &vp_y);
mode = FindMode(w, h);
if (mode)
{
XF86VidModeLockModeSwitch(disp, scr, 0);
std_vid_mode_cur = GetModeIndex(dotclock, &curmode);
XF86VidModeSwitchToMode(disp, scr, mode);
XF86VidModeSetViewPort(disp, scr, x, y);
XF86VidModeLockModeSwitch(disp, scr, 1);
}
}
else
{
mode = std_vid_modes[std_vid_mode_cur];
XF86VidModeLockModeSwitch(disp, scr, 0);
XF86VidModeSwitchToMode(disp, scr, mode);
XF86VidModeSetViewPort(disp, scr, vp_x, vp_y);
#if 0 /* No, don't lock or we can't switch resolution */
XF86VidModeLockModeSwitch(disp, scr, 1);
#endif
}
return mode;
}
static char
XHasDGA(void)
{
int ev_base, er_base;
if (XF86VidModeQueryExtension(disp, &ev_base, &er_base))
return 1;
else
return 0;
}
EWin *
GetZoomEWin(void)
{
return zoom_last_ewin;
}
void
ReZoom(EWin * ewin)
{
if ((InZoom()) && (ewin != zoom_last_ewin))
{
Zoom(NULL);
Zoom(ewin);
}
}
char
InZoom(void)
{
if (zoom_last_ewin)
return 1;
return 0;
}
void
ZoomInit(void)
{
if (XHasDGA())
{
FillStdVidModes();
if (std_vid_modes_num > 1)
zoom_can = 1;
}
}
static Win
ZoomMask(int x, int y, int w, int h)
{
Win win;
if (x < 0 || y < 0 || w <= 0 || h <= 0)
return 0;
win = ECreateWindow(VROOT, x, y, w, h, 0);
ESetWindowBackground(win, Dpy.pixel_black);
ERaiseWindow(win);
EMapWindow(win);
return win;
}
void
Zoom(EWin * ewin)
{
const XF86VidModeModeInfo *mode;
if (!zoom_can)
return;
if (!ewin)
{
if (zoom_last_ewin)
{
ewin = zoom_last_ewin;
/* XUngrabPointer(disp, CurrentTime); */
EwinMove(ewin, zoom_last_x, zoom_last_y);
if (zoom_mask_1)
EDestroyWindow(zoom_mask_1);
if (zoom_mask_2)
EDestroyWindow(zoom_mask_2);
if (zoom_mask_3)
EDestroyWindow(zoom_mask_3);
if (zoom_mask_4)
EDestroyWindow(zoom_mask_4);
SwitchRes(0, 0, 0, 0, 0);
EwinWarpTo(ewin);
ESync(0);
zoom_last_ewin = NULL;
}
return;
}
mode = SwitchRes(1, 0, 0, ewin->client.w, ewin->client.h);
if (mode)
{
int x1, y1, x2, y2, bl, br, bt, bb;
zoom_last_ewin = ewin;
zoom_last_x = EoGetX(ewin);
zoom_last_y = EoGetY(ewin);
x1 = (mode->hdisplay - ewin->client.w) / 2;
if (x1 < 0)
x1 = 0;
y1 = (mode->vdisplay - ewin->client.h) / 2;
if (y1 < 0)
y1 = 0;
x2 = mode->hdisplay - ewin->client.w - x1;
if (x2 < 0)
x2 = 0;
y2 = mode->vdisplay - ewin->client.h - y1;
if (y2 < 0)
y2 = 0;
EwinRaise(ewin);
EwinBorderGetSize(ewin, &bl, &br, &bt, &bb);
EwinMove(ewin, -bl + x1, -bt + y1);
FocusToEWin(ewin, FOCUS_SET);
EwinWarpTo(ewin);
#if 0 /* Doesn't work as intended */
XGrabPointer(disp, EwinGetClientXwin(ewin), True,
ButtonPressMask | ButtonReleaseMask |
PointerMotionMask | ButtonMotionMask |
EnterWindowMask | LeaveWindowMask,
GrabModeAsync, GrabModeAsync,
EwinGetClientXwin(ewin), None, CurrentTime);
#endif
zoom_mask_1 = ZoomMask(0, 0, x1, mode->vdisplay);
zoom_mask_2 = ZoomMask(0, 0, mode->hdisplay, y1);
zoom_mask_3 = ZoomMask(x1 + ewin->client.w, 0, x2, mode->vdisplay);
zoom_mask_4 = ZoomMask(0, y1 + ewin->client.h, mode->hdisplay, y2);
ESync(0);
}
}
#else
EWin *
GetZoomEWin(void)
{
return NULL;
}
void
ReZoom(EWin * ewin)
{
ewin = NULL;
}
char
InZoom(void)
{
return 0;
}
void
ZoomInit(void)
{
}
void
Zoom(EWin * ewin)
{
ewin = NULL;
}
#endif