diff options
Diffstat (limited to 'src/rmd_poll_events.c')
-rw-r--r-- | src/rmd_poll_events.c | 245 |
1 files changed, 245 insertions, 0 deletions
diff --git a/src/rmd_poll_events.c b/src/rmd_poll_events.c new file mode 100644 index 0000000..49f2478 --- /dev/null +++ b/src/rmd_poll_events.c @@ -0,0 +1,245 @@ +/****************************************************************************** +* recordMyDesktop * +******************************************************************************* +* * +* Copyright (C) 2006,2007,2008 John Varouhakis * +* * +* * +* This program is free software; you can redistribute it and/or modify * +* it under the terms of the GNU General Public License as published by * +* the Free Software Foundation; either version 2 of the License, or * +* (at your option) any later version. * +* * +* This program is distributed in the hope that it will be useful, * +* but WITHOUT ANY WARRANTY; without even the implied warranty of * +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * +* GNU General Public License for more details. * +* * +* You should have received a copy of the GNU General Public License * +* along with this program; if not, write to the Free Software * +* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * +* * +* * +* * +* For further information contact me at johnvarouhakis@gmail.com * +******************************************************************************/ + +#include "config.h" +#include "rmd_poll_events.h" + +#include "rmd_frame.h" +#include "rmd_macro.h" +#include "rmd_rectinsert.h" +#include "rmd_types.h" + +#include <X11/Xlib.h> +#include <X11/Xlibint.h> +#include <X11/extensions/Xdamage.h> + +#include <stdio.h> +#include <stdlib.h> +#include <signal.h> +#include <pthread.h> + + +static int clip_event_area(XDamageNotifyEvent *e, XRectangle *cliprect, XRectangle *res) +{ + +#if 0 + printf("got area %x,%x %x,%x\n", + e->area.x, + e->area.y, + e->area.width, + e->area.height); +#endif + + if ( e->area.x <= cliprect->x && + e->area.y <= cliprect->y && + e->area.width >= cliprect->width && + e->area.height >= cliprect->height) { + + /* area completely covers cliprect, cliprect becomes the area */ + res->x = cliprect->x; + res->y = cliprect->y; + res->width = cliprect->width; + res->height = cliprect->height; + + } else if ( e->area.x + e->area.width < cliprect->x || + e->area.x + e->area.width > cliprect->x + cliprect->width || + e->area.y + e->area.height < cliprect->y || + e->area.y + e->area.height > cliprect->y + cliprect->height) { + + /* area has at least one axis with zero overlap, so they can't overlap */ + return 0; + + } else { + + /* areas partially overlap */ + res->x = MAX(e->area.x, cliprect->x); + res->width = MIN(e->area.x + e->area.width, cliprect->x + cliprect->width) - res->x; + + res->y = MAX(e->area.y, cliprect->y); + res->height = MIN(e->area.y + e->area.height, cliprect->y + cliprect->height) - res->y; + + if (!res->width || !res->height) + return 0; + } + +#if 0 + printf("clipped to %x,%x %x,%x\n", + res->x, + res->y, + res->width, + res->height); +#endif + + return 1; +} + + +/* Try align xrect to even boundaries relative to cliprect, + * this is done for the UV routines which operate at 2x2 rgb pixel granularity. + */ +static void uv_align(XRectangle *cliprect, XRectangle *xrect) { + XRectangle rel; + + rel.x = xrect->x - cliprect->x; + rel.y = xrect->y - cliprect->y; + + if (rel.x % 2) { + rel.x -= 1; + rel.width = xrect->width + 1; + } else { + rel.width = xrect->width; + } + + if (rel.y % 2) { + rel.y -= 1; + rel.height = xrect->height + 1; + } else { + rel.height = xrect->height; + } + + /* XXX: note when cliprect prevents an even width, we can't do anything + * about it. rmd could force even-sized recording windows to prevent + * this, but that would be kind of annoying. For now it's assumed + * the UV routines will handle the exception - which might temporarily + * mean they just lop the odd row/column off the edge. + */ + if (rel.width % 2 && rel.width + rel.x < cliprect->x + cliprect->width) + rel.width++; + + if (rel.height % 2 && rel.height + rel.y < cliprect->y + cliprect->height) + rel.height++; +} + + +void rmdInitEventsPolling(ProgData *pdata) { + Window root_return, + parent_return, + *children; + unsigned int i, + nchildren; + + XSelectInput (pdata->dpy, pdata->specs.root, SubstructureNotifyMask); + + if (!pdata->args.full_shots) { + XQueryTree ( pdata->dpy, + pdata->specs.root, + &root_return, + &parent_return, + &children, + &nchildren); + + for (i = 0; i < nchildren; i++) { + XWindowAttributes attribs; + if (XGetWindowAttributes (pdata->dpy, children[i], &attribs)) { + if (!attribs.override_redirect && attribs.depth == pdata->specs.depth) + XDamageCreate( pdata->dpy, + children[i], + XDamageReportRawRectangles); + } + } + XFree(children); + XDamageCreate( pdata->dpy, + pdata->specs.root, + XDamageReportRawRectangles); + } +} + + +void rmdEventLoop(ProgData *pdata) { + int inserts = 0; + + XEvent event; + + while (XPending(pdata->dpy)) { + XNextEvent(pdata->dpy, &event); + if (event.type == KeyPress) { + XKeyEvent *e = (XKeyEvent *)(&event); + if (e->keycode == pdata->pause_key.key) { + int i = 0; + int found = 0; + for (i = 0; i < pdata->pause_key.modnum; i++) { + if (pdata->pause_key.mask[i] == e->state) { + found = 1; + break; + } + } + if (found) { + raise(SIGUSR1); + continue; + } + } + if (e->keycode == pdata->stop_key.key) { + int i = 0; + int found = 0; + for (i = 0; i < pdata->stop_key.modnum; i++) { + if (pdata->stop_key.mask[i] == e->state) { + found = 1; + break; + } + } + if (found) { + raise(SIGINT); + continue; + } + } + } else if (event.type == Expose) { + + if (event.xexpose.count != 0) + continue; + else if (!pdata->args.noframe) { + rmdDrawFrame( pdata->dpy, + pdata->specs.screen, + pdata->shaped_w, + pdata->brwin.rrect.width, + pdata->brwin.rrect.height); + } + + } else if (!pdata->args.full_shots) { + if (event.type == MapNotify ) { + XWindowAttributes attribs; + + if (!((XMapEvent *)(&event))->override_redirect&& + XGetWindowAttributes( pdata->dpy, + event.xcreatewindow.window, + &attribs)) { + + if (!attribs.override_redirect && attribs.depth == pdata->specs.depth) + XDamageCreate( pdata->dpy, + event.xcreatewindow.window, + XDamageReportRawRectangles); + } + } else if (event.type == pdata->damage_event + XDamageNotify ) { + XDamageNotifyEvent *e = (XDamageNotifyEvent *)&event; + XRectangle xrect; + + if (clip_event_area(e, &pdata->brwin.rrect, &xrect)) { + uv_align(&pdata->brwin.rrect, &xrect); + inserts += rmdRectInsert(&pdata->rect_root, &xrect); + } + } + } + } +} |