--- a/src/idle.c Thu Oct 26 02:12:34 2000 +0000 +++ b/src/idle.c Thu Oct 26 07:22:32 2000 +0000 @@ -1,648 +1,84 @@ -#if 0 -//---------------------------------------------------------------------------- -// This is a somewhat modified kscreensaver. -// The original copyright notice follows -// -//---------------------------------------------------------------------------- -// -// KDE screensavers -// -// This module is a heavily modified xautolock. -// The orignal copyright notice follows -// - -/***************************************************************************** +/* + * gaim + * + * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net> * - * xautolock - * ========= - * - * Authors : S. De Troch (SDT) + M. Eyckmans (MCE) - * - * Date : 22/07/90 - * - * --------------------------------------------------------------------------- - * - * Copyright 1990, 1992-1995 by S. De Troch and MCE. + * 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. * - * Permission to use, copy, modify and distribute this software and the - * supporting documentation without fee is hereby granted, provided that - * - * 1 : Both the above copyright notice and this permission notice - * appear in all copies of both the software and the supporting - * documentation. - * 2 : No financial profit is made out of it. + * 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. * - * THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO - * EVENT SHALL THEY BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL - * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA - * OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER - * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR - * PERFORMANCE OF THIS SOFTWARE. + * 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 * - *****************************************************************************/ - - - -/* - * Have a guess what this does... - * ============================== - * - * Warning for swm & tvtwm users : xautolock should *not* be compiled - * with vroot.h, because it needs to know the real root window. */ #ifdef HAVE_CONFIG_H -#include <config.h> -#endif - -#if defined(hpux) || defined (__hpux) -#ifndef _HPUX_SOURCE -#define _HPUX_SOURCE -#endif /* _HPUX_SOURCE */ -#endif /* hpux || __hpux */ - -#include <stdio.h> -#include <string.h> -#include <ctype.h> - -#ifdef VMS -#include <ssdef.h> -#include <processes.h> /* really needed? */ -#endif /* VMS */ - -#include <X11/Xlib.h> -#include <X11/Xatom.h> -#include <X11/Xresource.h> - -#include <time.h> -#include <signal.h> -#include <sys/wait.h> -#include <sys/types.h> - -#ifdef HAVE_SYS_M_WAIT_H -#include <sys/m_wait.h> -#endif - -#ifdef HAVE_MALLOC_H -#include <malloc.h> -#endif - -#ifdef HAVE_UNISTD_H -#include <unistd.h> +#include "../config.h" #endif -#include <stdlib.h> - -#include <gdk/gdkx.h> -#include <gtk/gtk.h> -#include "gaim.h" - -void initAutoLock(); -void cleanupAutoLock(); - -/* - * Usefull macros and customization stuff - * ====================================== - */ -#define PP(x) x - -#ifdef VMS -#define ALL_OK 1 /* for use by exit () */ -#define PROBLEMS SS$_ABORT - /* for use by exit () */ -#else /* VMS */ -#define ALL_OK 0 /* for use by exit () */ -#define PROBLEMS 1 /* for use by exit () */ -#endif /* VMS */ - - -#define CREATION_DELAY 30 /* should be > 10 and - < min (45,(MIN_MINUTES*30)) */ -#define TIME_CHANGE_LIMIT 120 /* if the time changes by more - than x secs then we will - assume someone has changed - date or machine has suspended */ - - -#ifndef HasVFork -#define vfork fork -#endif /* HasVFork */ - -#define Error0(str) fprintf (stderr, str) -#define SetTrigger(delta) trigger = time ((time_t*) NULL) + delta - -static caddr_t ch_ptr; /* this is dirty */ -#define Skeleton(t,s) (ch_ptr = (Caddrt) malloc ((Unsigned) s), \ - (ch_ptr == (Caddrt) NULL) \ - ? (Error0 ("Out of memory.\n"), \ - exit (PROBLEMS), \ - /*NOTREACHED*/ (t*) NULL \ - ) \ - : (t*) ch_ptr \ - ) \ - -#define New(tp) Skeleton (tp, sizeof (tp)) - - - -/* - * New types - * ========= - */ -#if defined (apollo) || defined (news1800) -typedef int (*XErrorHandler) PP((Display*, - XErrorEvent*)); -#endif /* apollo || news1800 */ - -#if defined (news1800) || defined (sun386) -typedef int pid_t; -#endif /* news1800 || sun386*/ - -#ifdef VMS -typedef long pid_t; -#endif /* VMS */ - -#define Void void /* no typedef because of VAX */ -typedef int Int; -typedef char Char; -typedef char* String; -typedef int Boolean; -typedef caddr_t Caddrt; -typedef unsigned int Unsigned; -typedef unsigned long Huge; - -typedef struct QueueItem_ - { - Window window; /* as it says */ - time_t creationtime; /* as it says */ - struct QueueItem_* next; /* as it says */ - struct QueueItem_* prev; /* as it says */ - } aQueueItem, *QueueItem; - -typedef struct Queue_ - { - struct QueueItem_* head; /* as it says */ - struct QueueItem_* tail; /* as it says */ - } aQueue, *Queue; - +#include <time.h> +#include <stdio.h> +#include <unistd.h> +#include <aim.h> -/* - * Function declarations - * ===================== - */ -#if defined(news1800) -extern Void* malloc PP((Unsigned)); -#endif /* news1800 */ - -static int EvaluateCounter PP((Display*)); -static int QueryPointer PP((Display*, int)); -static int ProcessEvents PP((Display*, Queue, int)); -static Queue NewQueue PP((Void)); -static Void AddToQueue PP((Queue, Window)); -static Void ProcessQueue PP((Queue, Display*, time_t)); -static Void SelectEvents PP((Display*, Window, Boolean)); - - -/* - * Global variables - * ================ - */ -static time_t trigger = 0; /* as it says */ -static time_t time_limit = IDLE_REPORT_TIME; /* as it says */ - -/* - * Functions related to the window queue - * ===================================== - * - * Function for creating a new queue - * --------------------------------- - */ -static Queue NewQueue () - -{ - Queue queue; /* return value */ - - queue = New (aQueue); - queue->tail = New (aQueueItem); - queue->head = New (aQueueItem); - - queue->tail->next = queue->head; - queue->head->prev = queue->tail; - queue->tail->prev = queue->head->next = (QueueItem) NULL; - - return queue; -} - - -/* - * Function for adding an item to a queue - * -------------------------------------- - */ -static Void AddToQueue (Queue queue, Window window) -{ - QueueItem newq; /* new item */ - - newq = New (aQueueItem); - - newq->window = window; - newq->creationtime = time ((time_t*) NULL); - newq->next = queue->tail->next; - newq->prev = queue->tail; - queue->tail->next->prev = newq; - queue->tail->next = newq; -} - -/* - * Function for processing those entries that are old enough - * --------------------------------------------------------- - */ -static Void ProcessQueue (Queue queue, Display *d, time_t age) -{ - QueueItem current; /* as it says */ - time_t now; /* as it says */ - - time (&now); - current = queue->head->prev; +#ifdef USE_SCREENSAVER +#include <X11/Xlib.h> +#include <X11/Xutil.h> +#include <X11/extensions/scrnsaver.h> +#endif /* USE_SCREENSAVER */ - while ( current->prev && current->creationtime + age < now ) - { - SelectEvents (d, current->window, False); - current = current->prev; - free (current->next); - } - - current->next = queue->head; - queue->head->prev = current; -} - - -static Void FreeQueue( Queue queue ) -{ - QueueItem current; /* as it says */ - - current = queue->head->prev; - - while ( current->prev ) - { - current = current->prev; - free(current->next); - } - - free(current); - free(queue); -} - - -/* - * Functions related to (the lack of) user activity - * ================================================ - * - * Function for processing the event queue - * --------------------------------------- - */ -static int ProcessEvents (Display *d, Queue queue, int until_idle) -{ - XEvent event; /* as it says */ - - /* - * Read whatever is available for reading. - */ - while (XPending (d)) - { - if (XCheckMaskEvent (d, SubstructureNotifyMask, &event)) - { - if ((event.type == CreateNotify) && until_idle) - { - AddToQueue (queue, event.xcreatewindow.window); - } - } - else - { - XNextEvent (d, &event); - } - - - /* - * Reset the counter if and only if the event is a KeyPress - * event *and* was not generated by XSendEvent (). - */ - if ( event.type == KeyPress && !event.xany.send_event ) - { - if (!until_idle) /* We've become un-idle */ - return 1; - SetTrigger (time_limit); - } - } - - - /* - * Check the window queue for entries that are older than - * CREATION_DELAY seconds. - */ - ProcessQueue (queue, d, (time_t) CREATION_DELAY); - return 0; -} +#include "multi.h" +#include "gaim.h" -/* - * Function for monitoring pointer movements - * ----------------------------------------- - */ -static int QueryPointer (Display *d, int until_idle) +gint check_idle(struct gaim_connection *gc) { - Window dummy_w; /* as it says */ - Int dummy_c; /* as it says */ - Unsigned mask; /* modifier mask */ - Int root_x; /* as it says */ - Int root_y; /* as it says */ - Int i; /* loop counter */ - static Window root; /* root window the pointer is on */ - static Screen* screen; /* screen the pointer is on */ - static Unsigned prev_mask = 0; /* as it says */ - static Int prev_root_x = -1; /* as it says */ - static Int prev_root_y = -1; /* as it says */ - static Boolean first_call = TRUE; /* as it says */ - - - /* - * Have a guess... - */ - if (first_call) - { - first_call = FALSE; - root = DefaultRootWindow (d); - screen = ScreenOfDisplay (d, DefaultScreen (d)); - } - - - /* - * Find out whether the pointer has moved. Using XQueryPointer for this - * is gross, but it also is the only way never to mess up propagation - * of pointer events. - * - * Remark : Unlike XNextEvent(), XPending () doesn't notice if the - * connection to the server is lost. For this reason, earlier - * versions of xautolock periodically called XNoOp (). But - * why not let XQueryPointer () do the job for us, since - * we now call that periodically anyway? - */ - if (!XQueryPointer (d, root, &root, &dummy_w, &root_x, &root_y, - &dummy_c, &dummy_c, &mask)) - { - /* - * Pointer has moved to another screen, so let's find out which one. - */ - for (i = -1; ++i < ScreenCount (d); ) - { - if (root == RootWindow (d, i)) - { - screen = ScreenOfDisplay (d, i); - break; - } - } - } - - if ( root_x != prev_root_x - || root_y != prev_root_y - || mask != prev_mask - ) - { - prev_root_x = root_x; - prev_root_y = root_y; - prev_mask = mask; - SetTrigger (time_limit); - if (!until_idle) - return 1; - } - - return 0; - -} + time_t t; +#ifdef USE_SCREENSAVER + static XScreenSaverInfo *mit_info = NULL; + Display *d = XOpenDisplay((char*)NULL); + time_t idle_time; +#endif -/* - * Function for deciding whether to lock - * ------------------------------------- - */ -static int EvaluateCounter (Display *d) -{ - time_t now = 0; /* as it says */ - - /* - * Now trigger the notifier if required. - */ - time (&now); - - /* - * Finally fire up the locker if time has come. - */ - if (now >= trigger) - { - SetTrigger (time_limit); - return TRUE; - } + /* Not idle, really... :) */ + update_all_buddies(); - return FALSE; -} - -/* - * Function for selecting events on a tree of windows - * -------------------------------------------------- - */ -static Void SelectEvents (Display *d, Window window, Boolean substructure_only) -{ - Window root; /* root window of this window */ - Window parent; /* parent of this window */ - Window* children; /* children of this window */ - Unsigned nof_children = 0; /* number of children */ - Unsigned i; /* loop counter */ - XWindowAttributes attribs; /* attributes of the window */ - - - /* - * Start by querying the server about parent and child windows. - */ - if (!XQueryTree (d, window, &root, &parent, &children, &nof_children)) - { - return; - } - + plugin_event(event_blist_update, 0, 0, 0, 0); + + time(&t); - /* - * Build the appropriate event mask. The basic idea is that we don't - * want to interfere with the normal event propagation mechanism if - * we don't have to. - */ - if (substructure_only) - { - XSelectInput (d, window, SubstructureNotifyMask); - } - else - { - if (parent == None) /* the *real* rootwindow */ - { - attribs.all_event_masks = - attribs.do_not_propagate_mask = KeyPressMask; - } - else if (XGetWindowAttributes (d, window, &attribs) == 0) - { - return; - } - - XSelectInput (d, window, SubstructureNotifyMask - | ( ( attribs.all_event_masks - | attribs.do_not_propagate_mask) - & KeyPressMask)); - } - - - /* - * Now do the same thing for all children. - */ - for (i = 0; i < nof_children; ++i) - { - SelectEvents (d, children[i], substructure_only); - } - - if (nof_children) XFree ((Char*) children); -} - - -int catchFalseAlarms( Display *d, XErrorEvent *x ) -{ - return 0; -} - -Queue windowQueue; -Window hiddenWin; /* hidden window */ - -void initAutoLock() -{ - Display* d; /* display pointer */ - Window r; /* root window */ - Int s; /* screen index */ - XSetWindowAttributes attribs; /* for dummy window */ - int (*oldHandler)(Display *, XErrorEvent *); - - d = GDK_DISPLAY(); - - oldHandler = XSetErrorHandler( catchFalseAlarms ); - XSync (d, 0); - - windowQueue = NewQueue (); - - for (s = -1; ++s < ScreenCount (d); ) - { - AddToQueue (windowQueue, r = RootWindowOfScreen (ScreenOfDisplay (d, s))); - SelectEvents (d, r, True); - } + if (report_idle == 0) + return TRUE; + /* + if (gc->is_idle) { + fprintf (stderr, "\tgc->is_idle\n"); + return TRUE; + } + */ - /* - * Get ourselves a dummy window in order to allow display and/or - * session managers etc. to use XKillClient() on us (e.g. xdm when - * not using XDMCP). - * - * I'm not sure whether the window needs to be mapped for xdm, but - * the default set up Sun uses for OpenWindows and olwm definitely - * requires it to be mapped. - */ - attribs.override_redirect = True; - hiddenWin = XCreateWindow (d, DefaultRootWindow (d), -100, -100, 1, 1, 0, - CopyFromParent, InputOnly, CopyFromParent, CWOverrideRedirect, - &attribs); - - XMapWindow (d, hiddenWin ); - - XSetErrorHandler( oldHandler ); -} - -/* I don't think this should be needed, but leaving the code here - in case I change my mind. */ -/* -void cleanupAutoLock() -{ - int (*oldHandler)(Display *, XErrorEvent *); - oldHandler = XSetErrorHandler( catchFalseAlarms ); - - FreeQueue( windowQueue ); - XDestroyWindow( GDK_DISPLAY(), hiddenWin ); - XSetErrorHandler( oldHandler ); -} -*/ - -/* - * Main function - * ------------- - */ -void waitIdle( int timeout, int until_idle ) -{ - Display* d; /* display pointer */ - int (*oldHandler)(Display *, XErrorEvent *); - time_t now, prev; - - time_limit = timeout; - - d = GDK_DISPLAY(); +#ifdef USE_SCREENSAVER + if (report_idle == IDLE_SCREENSAVER) { + if (mit_info == NULL) { + mit_info = XScreenSaverAllocInfo (); + } + XScreenSaverQueryInfo (d, DefaultRootWindow(d), mit_info); + idle_time = (mit_info->idle)/1000; + } else +#endif /* USE_SCREENSAVER */ + idle_time = t - gc->lastsent; - oldHandler = XSetErrorHandler( catchFalseAlarms ); - - SetTrigger (time_limit); - - time(&prev); + if (idle_time > 600) { /* 10 minutes! */ + serv_set_idle(gc, idle_time); + gc->is_idle = 1; + } else + serv_touch_idle(gc); - /* - * Main event loop. - */ - while ( 1 ) - { - if (ProcessEvents (d, windowQueue, until_idle)) - break; - if (QueryPointer (d, until_idle)) - break; - - if (until_idle) { - time(&now); - - if ((now > prev && now - prev > TIME_CHANGE_LIMIT) || - (prev > now && prev - now > TIME_CHANGE_LIMIT+1)) - { - /* the time has changed in one large jump. This could be because the - date was changed, or the machine was suspended. We'll just - reset the triger. */ - SetTrigger (time_limit); - } - - prev = now; - - if ( EvaluateCounter (d) ) - break; - } - - /* - * It seems that, on some operating systems (VMS to name just one), - * sleep () can be vastly inaccurate: sometimes 60 calls to sleep (1) - * add up to only 30 seconds or even less of sleeping. Therefore, - * as of patchlevel 9 we no longer rely on it for keeping track of - * time. The only reason why we still call it, is to make xautolock - * (which after all uses a busy-form-of-waiting algorithm), less - * processor hungry. - */ - sleep (1); - } - - XSetErrorHandler( oldHandler ); + return TRUE; } - -void idle_main(pid_t gaimpid) { - initAutoLock(); - while (1) { - waitIdle(IDLE_REPORT_TIME, 1); - kill(gaimpid, SIGALRM); - sleep(1); /* Just to be safe */ - waitIdle(1, 0); - kill(gaimpid, SIGALRM); - } -} - - -#endif \ No newline at end of file