[Xfce4-commits] <xfwm4:ochosi/tabwin> Implement zooming.
Alistair Buxton
noreply at xfce.org
Wed Dec 11 23:25:03 CET 2013
Updating branch refs/heads/ochosi/tabwin
to e7da725aab39018f54383dc6e8a64eccd8793035 (commit)
from ab3de90429ae015e7f657f44f10f281120bbbe7a (commit)
commit e7da725aab39018f54383dc6e8a64eccd8793035
Author: Alistair Buxton <a.j.buxton at gmail.com>
Date: Sat Nov 16 16:25:35 2013 +0000
Implement zooming.
This implements zooming when the compositor is enabled. To zoom in,
hold the key used to grab and move windows (usually alt) and scroll
up with the mouse wheel. Scroll down to zoom out.
This works by transforming the offscreen buffer where windows are
composited when rendering it back to the screen.
src/compositor.c | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
src/compositor.h | 4 ++
src/events.c | 8 ++--
src/screen.h | 4 ++
4 files changed, 137 insertions(+), 7 deletions(-)
diff --git a/src/compositor.c b/src/compositor.c
index 5709d38..a8abd80 100644
--- a/src/compositor.c
+++ b/src/compositor.c
@@ -1385,6 +1385,12 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
{
screen_info->rootBuffer = create_root_buffer (screen_info);
g_return_if_fail (screen_info->rootBuffer != None);
+
+ memset(screen_info->transform.matrix, 0, 9);
+ screen_info->transform.matrix[0][0] = 1<<16;
+ screen_info->transform.matrix[1][1] = 1<<16;
+ screen_info->transform.matrix[2][2] = 1<<16;
+ screen_info->zoomed = 0;
}
/* Copy the original given region */
@@ -1515,9 +1521,17 @@ paint_all (ScreenInfo *screen_info, XserverRegion region)
}
TRACE ("Copying data back to screen");
- /* Set clipping back to the given region */
- XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, region);
-
+ if(screen_info->zoomed)
+ {
+ /* Fixme: copy back whole screen if zoomed
+ It would be better to scale the clipping region if possible. */
+ XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, None);
+ }
+ else
+ {
+ /* Set clipping back to the given region */
+ XFixesSetPictureClipRegion (dpy, screen_info->rootBuffer, 0, 0, region);
+ }
#ifdef HAVE_LIBDRM
#if TIMEOUT_REPAINT
use_dri = dri_enabled (screen_info);
@@ -2406,6 +2420,61 @@ destroy_win (DisplayInfo *display_info, Window id)
}
}
+void
+recenter_zoomed_area (ScreenInfo *screen_info, int x_root, int y_root)
+{
+ int zf = screen_info->transform.matrix[0][0];
+ double zoom = XFixedToDouble(zf);
+ Display *dpy = screen_info->display_info->dpy;
+
+ if(screen_info->zoomed)
+ {
+ int xp = x_root * (1-zoom);
+ int yp = y_root * (1-zoom);
+ screen_info->transform.matrix[0][2] = (xp<<16);
+ screen_info->transform.matrix[1][2] = (yp<<16);
+ }
+
+ if(zf > (1<<14) && zf < (1<<16))
+ XRenderSetPictureFilter(dpy, screen_info->rootBuffer, "bilinear", NULL, 0);
+ else
+ XRenderSetPictureFilter(dpy, screen_info->rootBuffer, "nearest", NULL, 0);
+
+ XRenderSetPictureTransform(dpy, screen_info->rootBuffer, &screen_info->transform);
+
+ damage_screen(screen_info);
+}
+
+static gboolean
+zoom_timeout_cb (gpointer data)
+{
+ ScreenInfo *screen_info;
+ Window root_return;
+ Window child_return;
+ int x_root, y_root;
+ int x_win, y_win;
+ unsigned int mask;
+ static int x_old=-1, y_old=-1;
+
+ screen_info = (ScreenInfo *) data;
+
+ if(!screen_info->zoomed)
+ {
+ screen_info->zoom_timeout_id = 0;
+ return FALSE; /* stop calling this callback */
+ }
+
+ XQueryPointer (screen_info->display_info->dpy, screen_info->xroot,
+ &root_return, &child_return,
+ &x_root, &y_root, &x_win, &y_win, &mask);
+ if(x_old != x_root || y_old != y_root)
+ {
+ x_old = x_root; y_old = y_root;
+ recenter_zoomed_area(screen_info, x_root, y_root);
+ }
+ return TRUE;
+}
+
static void
compositorHandleDamage (DisplayInfo *display_info, XDamageNotifyEvent *ev)
{
@@ -2967,6 +3036,57 @@ compositorHandleEvent (DisplayInfo *display_info, XEvent *ev)
}
void
+compositorZoomIn (ScreenInfo *screen_info, XButtonEvent *ev)
+{
+#ifdef HAVE_COMPOSITOR
+ screen_info->transform.matrix[0][0] -= 4096;
+ screen_info->transform.matrix[1][1] -= 4096;
+
+ if(screen_info->transform.matrix[0][0] < (1<<10))
+ {
+ screen_info->transform.matrix[0][0] = (1<<10);
+ screen_info->transform.matrix[1][1] = (1<<10);
+ }
+
+ screen_info->zoomed = 1;
+ if(!screen_info->zoom_timeout_id)
+ {
+ int timeout_rate = 30; /* per second */
+#ifdef HAVE_RANDR
+ if (screen_info->display_info->have_xrandr)
+ {
+ timeout_rate = screen_info->refresh_rate/2;
+ }
+#endif /* HAVE_RANDR */
+ screen_info->zoom_timeout_id = g_timeout_add ((1000/timeout_rate), zoom_timeout_cb, screen_info);
+ }
+ recenter_zoomed_area(screen_info, ev->x_root, ev->y_root);
+#endif /* HAVE_COMPOSITOR */
+}
+
+void
+compositorZoomOut (ScreenInfo *screen_info, XButtonEvent *ev)
+{
+#ifdef HAVE_COMPOSITOR
+ if(screen_info->zoomed)
+ {
+ screen_info->transform.matrix[0][0] += 4096;
+ screen_info->transform.matrix[1][1] += 4096;
+
+ if(screen_info->transform.matrix[0][0] >= (1<<16))
+ {
+ screen_info->transform.matrix[0][0] = (1<<16);
+ screen_info->transform.matrix[1][1] = (1<<16);
+ screen_info->zoomed = 0;
+ screen_info->transform.matrix[0][2] = 0;
+ screen_info->transform.matrix[1][2] = 0;
+ }
+ recenter_zoomed_area(screen_info, ev->x_root, ev->y_root);
+ }
+#endif /* HAVE_COMPOSITOR */
+}
+
+void
compositorInitDisplay (DisplayInfo *display_info)
{
#ifdef HAVE_COMPOSITOR
@@ -3171,6 +3291,8 @@ compositorManageScreen (ScreenInfo *screen_info)
screen_info->compositor_active = TRUE;
screen_info->wins_unredirected = 0;
screen_info->compositor_timeout_id = 0;
+ screen_info->zoomed = 0;
+ screen_info->zoom_timeout_id = 0;
screen_info->damages_pending = FALSE;
XClearArea (display_info->dpy, screen_info->output, 0, 0, 0, 0, TRUE);
diff --git a/src/compositor.h b/src/compositor.h
index 017ffc1..fbb0fee 100644
--- a/src/compositor.h
+++ b/src/compositor.h
@@ -53,6 +53,10 @@ void compositorResizeWindow (DisplayInfo *,
int);
void compositorHandleEvent (DisplayInfo *,
XEvent *);
+void compositorZoomIn (ScreenInfo *,
+ XButtonEvent *);
+void compositorZoomOut (ScreenInfo *,
+ XButtonEvent *);
void compositorInitDisplay (DisplayInfo *);
void compositorSetCompositeMode (DisplayInfo *,
gboolean);
diff --git a/src/events.c b/src/events.c
index 4b49171..3701d75 100644
--- a/src/events.c
+++ b/src/events.c
@@ -903,16 +903,16 @@ handleButtonPress (DisplayInfo *display_info, XButtonEvent * ev)
part = edgeGetPart (c, ev);
edgeButton (c, part, ev);
}
-#if 0 /* Binding the alt+scroll wheel to switch app/window is not handy, disabling for now */
+#ifdef HAVE_COMPOSITOR
else if ((ev->button == Button4) && (state) && (state == screen_info->params->easy_click))
{
- clientSwitchWindow ();
+ compositorZoomIn(screen_info, ev);
}
else if ((ev->button == Button5) && (state) && (state == screen_info->params->easy_click))
{
- clientSwitchApp ();
+ compositorZoomOut(screen_info, ev);
}
-#endif
+#endif /* HAVE_COMPOSITOR */
else if (WIN_IS_BUTTON (win))
{
if (ev->button <= Button3)
diff --git a/src/screen.h b/src/screen.h
index 8589374..ad5ce47 100644
--- a/src/screen.h
+++ b/src/screen.h
@@ -182,6 +182,10 @@ struct _ScreenInfo
guint compositor_timeout_id;
+ XTransform transform;
+ gboolean zoomed;
+ guint zoom_timeout_id;
+
#ifdef HAVE_LIBDRM
gint dri_fd;
gboolean dri_secondary;
More information about the Xfce4-commits
mailing list