bug-hurd
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Screensaver patch


From: M. Gerards
Subject: Screensaver patch
Date: Mon, 19 May 2003 19:52:25 +0200
User-agent: Internet Messaging Program (IMP) 3.1

Hi,

Here is a patch to add screensaver support to the console-client and 3
screensavers are included with this patch! :)

The first screensaver is blank, it only supports the blank powerlevel, a
powerlevel I use for software blanking (iow, clearing the screen).

The second is blank_vga. Currently it only supports the sleep powerlevel
(disable the video signal). But many more powerlevels will me added.

The last is life, it is a conway's game of life screensaver. This screensaver
works on all text displays.

Atfer applying this patch you will have these new arguments for the console 
client:

 -e, --saver-events=EVENTS  Set the event to awake the screensaver in EVENT.
                             The events should one or more of: INPUT, OUTPUT,
                             BELL, FLASH.

 Set screensaver timeouts. Screensavers are run in the order blank, sleep,
 standby, suspend, poweroff.
  -b, --blank=SECONDS        Blank after SECONDS second
  -p, --poweroff=SECONDS     Poweroff after SECONDS second
  -s, --sleep=SECONDS        Sleep after SECONDS second
  -t, --standby=SECONDS      Sleep after SECONDS second
  -u, --suspend=SECONDS      Suspend after SECONDS second

What are events?

An event is something that stops the screensaver. You can configure one or more
event to stop it and by default INPUT is used.

example:

console -b 60 -e INPUT,BELL -d vga -d pc_kbd -d blank_vga /dev/vcs
(Stops blanking when the console beeps or when a key is pressed)

And what about those powerlevels?

Powerlevel is the amount of power that should be saved by saving. Two extremes
are BLANK (safe no power, just prevent the picture from burning in or show nice
graphics) and POWEROFF (Poweroff the output device, the monitor in most cases).

Every screensaver can support one or more powerlevels. You can also tell
screensaver to respond on powerlevels (-d blank -d POWEROFF for example).

You can tell the console after how much time a screensaver should be started,
this can be controlled per powerlevel.

example:
console -b 60 -s 300 -d vga -d pc_kbd -d blank_vga -d life /dev/vcs
(Start the life screensaver after 60 seconds, the blank_vga screensaver will be
started after 300 seconds)

I hope it is clear how this works (please ask if it is not!).

Finally I'd like to add that the patch to add the get_dimensions interface to
the console display driver should be applied before this patch.

Enjoy.

Thanks,
Marco

2003-05-19  Marco Gerards  <metgerards@student.han.nl>

        * console.c (screensaver_time): New variable to time screensaver
        startup.
        (powerlevel): New variable. array with powerlevel timings.
        (first_powerlevel): New variable.
        (last_lowerlevel): Likewise.
        (current_powerlevel): Likewise.
        (screensaver_events): New variable. Bitmap of accepted events.
        (start_screensaver): New funcion.
        (console_screensaver_event): Likewise.
        (cons_vcons_add): Make it work while a screensaver is running.
        (cons_vcons_write): Generate a screensaver event.
        (cons_vcons_beep): Likewise.
        (cons_vcons_flash): Likewise.
        (options): Add options for handling events and powerlevels.
        (parse_opt): Add local function set_powerlevel. Parse new options.
        (main): Initialize the screensaver and timer.
        * driver.c (driver_init): Initialize the screensaver driver list.
        (ADD_REMOVE_COMPONENT): Add the screensaver too.
        * driver.h (driver.h): Added include.
        (screensaver_iterate): New macro.
        (struct screensaver): New struct.
        (screensaver_t): New type.
        * pc-kbd.c (input_loop): Generate a screensaver event. Don't report 
input when
        the event stopped a screensaver.
        * screensaver.h: New file.
        * blank.c: New file.
        * blank_vga.c: New file.
        * life.c: New file.
        (Makefile): Add screensavers blank, blank_vga and life.
        

diff -upN console-client-with_get_dim/blank.c console-client/blank.c
--- console-client-with_get_dim/blank.c 1970-01-01 01:00:00.000000000 +0100
+++ console-client/blank.c      2003-05-19 20:12:52.000000000 +0200
@@ -0,0 +1,250 @@
+/* blank.c - Portable screensaver driver to blank the screen.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Marco Gerards.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd 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, or (at
+   your option) any later version.
+
+   The GNU Hurd 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, USA. */
+
+#include <assert.h>
+#include <sys/io.h>
+#include <argp.h>
+#include <string.h>
+
+#include "driver.h"
+
+
+/* Forward declaration.  */
+static struct screensaver_ops blank_ops;
+
+/* Bitmap of supported powermodes.  */
+static int powermodes;
+
+/* Clear the screen.  */
+static void
+display_clear (void)
+{
+  display_iterate 
+    {
+      int width;
+      int height;
+      conchar_t space = 
+       {
+         .chr = ' '
+       };
+      conchar_t *spaces;
+
+      
+      display->ops->get_dimensions (display->handle, &width, &height);
+
+      spaces = alloca (width * sizeof (conchar_t));
+      if (!spaces)
+       return;
+
+      /* Create an empty line.  */
+      for (int i = 0; i < width; i++)
+       spaces[i] = space;
+
+      /* Clear the screen.  */
+      if (display->ops->clear)
+       display->ops->clear (display->handle, width * height, 0, 0);
+
+      /* Clear the screen line by line.  */
+      if (display->ops->write)
+       for (int y = 0; y < height; y++)
+         display->ops->write (display->handle, spaces, width, 0, y);
+
+      /* Hide the cursor.  */
+      if (display->ops->set_cursor_status)
+       display->ops->set_cursor_status (display->handle, 
+                                        CONS_CURSOR_INVISIBLE);
+
+      /* Update the screen.  */
+      if (display->ops->update)
+       display->ops->update (display->handle);
+    }
+}
+
+
+struct arguments
+{
+  int powermodes;
+};
+
+const char *argp_program_version = "blank 0.1";
+static struct argp_option options[] = {
+  {"powermodes",     'p', "POWERMODES",          0,
+   "One or more of the the modes BLANK, SLEEP, STANDBY, SUSPEND, POWEROFF " 
+   "(Default BLANK)" },
+  {0}
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  struct arguments *arguments = state->input;
+
+  switch (key)
+    {
+    case 'p':
+      {
+       char *args = strdupa (arg);
+       char *curarg;
+       arguments->powermodes = 0;
+      
+       /* Split a comma seperated string.  */
+       curarg = strtok (args, ",");
+       while (curarg)
+         {
+           if (!strcasecmp (curarg, "BLANK"))
+             arguments->powermodes |= BLANK;
+           else if (!strcasecmp (curarg, "SLEEP"))
+             arguments->powermodes |= SLEEP;
+           else if (!strcasecmp (curarg, "STANDBY"))
+             arguments->powermodes |= STANDBY;
+           else if (!strcasecmp (curarg, "SUSPEND"))
+             arguments->powermodes |= SUSPEND;
+           else if (!strcasecmp (curarg, "POWEROFF"))
+             arguments->powermodes |= POWEROFF;
+
+           curarg = strtok (NULL, ",");
+         }
+      }
+      break;
+    case ARGP_KEY_ARG:
+      argp_usage (state);
+      break;
+    case ARGP_KEY_END:
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp argp = {options, parse_opt, 0, 0};
+
+
+static error_t
+blank_init (void **handle, int no_exit, int argc, char *argv[], int *next)
+{
+  int lastarg;
+  struct arguments arguments;
+
+  /* FIXME: argp is reentrant(!?).  */
+
+  /* If a driver is loaded after this one, stop parsing before the
+     "-d".  */
+  for (lastarg = *next; lastarg < argc; lastarg++)
+    if (!strcmp (argv[lastarg], "-d"))
+      break;
+
+  /* If this driver is the last don't parse the last argument because
+     it is an argument for the console-client.  */
+  if (lastarg == argc)
+    lastarg--;
+
+  /* By default only handle sleep and blank.  */
+  arguments.powermodes = BLANK;
+
+  if (lastarg  > *next)
+    {
+      /* Prepare arguments for argp parsing.  */
+      int new_argc = lastarg - *next + 1;
+      char **new_argv = &argv[*next - 1];
+      char *oldarg = argv[0];
+      /* XXX: Is hardcoded.  */
+      argv[0] = "blank";
+
+      argp_parse (&argp, new_argc, new_argv, 0, 0, &arguments);
+      argv[0] = oldarg;
+      *next = lastarg;
+    }
+
+  powermodes = arguments.powermodes;
+  return 0;
+}
+
+/* Start the screensaver driver.  */
+static error_t
+blank_start (void *handle)
+{
+  error_t err;
+
+  err = driver_add_screensaver (&blank_ops, NULL);
+  return err;
+}
+
+/* Make the screensaver sleep with power level LEVEL. Immediatly
+   return. */
+static void
+blank_sleep (void *handle, power_level_t level)
+{
+  switch (level)
+    {
+    case pl_blank:
+      if (!(powermodes & BLANK))
+       break;
+      display_clear ();
+      break;
+    case pl_sleep:
+      if (!(powermodes & SLEEP))
+       break;
+      display_clear ();
+      break;
+    case pl_standby:
+      if (!(powermodes & STANDBY))
+       break;
+      display_clear ();
+      break;
+    case pl_suspend:
+      if (!(powermodes & SUSPEND))
+       break;
+      display_clear ();
+      break;
+    case pl_poweroff:
+      if (!(powermodes & POWEROFF))
+       break;
+      display_clear ();
+      break;
+    }
+}
+
+/* Make the screensaver wake up.  */
+static void
+blank_wakeup (void *handle)
+{
+  /* No need to wake it up, the refesh will be enough.  */
+}
+
+/* Deinitialize the screensaver driver.  */
+static error_t
+blank_fini (void *handle, int force)
+{
+  return 0;
+}
+
+struct driver_ops driver_blank_ops =
+  {
+    blank_init,
+    blank_start,
+    blank_fini
+  };
+
+static struct screensaver_ops blank_ops =
+  {
+    blank_sleep,
+    blank_wakeup
+  };
diff -upN console-client-with_get_dim/blank_vga.c console-client/blank_vga.c
--- console-client-with_get_dim/blank_vga.c     1970-01-01 01:00:00.000000000 
+0100
+++ console-client/blank_vga.c  2003-05-19 18:58:52.000000000 +0200
@@ -0,0 +1,251 @@
+/* blank_vga.c - Screensaver driver to blank the screen and save power
+   using VGA hardware.
+
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Marco Gerards.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd 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, or (at
+   your option) any later version.
+
+   The GNU Hurd 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, USA. */
+
+#include <assert.h>
+#include <sys/io.h>
+#include <argp.h>
+#include <string.h>
+
+#include "driver.h"
+
+
+/* The sequencer address register selects the sub-register of the
+   sequencer that is accessed through the sequencer data register.  */
+#define VGA_SEQ_ADDR_REG               0x3c4
+#define VGA_SEQ_DATA_REG               0x3c5
+
+#define VGA_SEQ_CLOCK_MODE_ADDR                0x01
+
+/* When set the display output is disabled.  */
+#define        VGA_SEQ_CLOCK_MODE_SCROFF       0x20
+
+
+#define        DISPLAY_ON      0
+#define        DISPLAY_OFF     1
+
+/* The display is on by default.  */
+static int display_status = DISPLAY_ON;
+
+/* The old value of the clock mode sequence register.  */
+static int old_seq;
+
+/* Forward declaration.  */
+static struct screensaver_ops blank_vga_ops;
+
+/* Bitmap of supported powermodes.  */
+static int powermodes;
+
+/* Disable the VGA video signal.  */
+static void
+display_disable (void)
+{
+  outb (VGA_SEQ_CLOCK_MODE_ADDR, VGA_SEQ_ADDR_REG);
+  old_seq = inb (VGA_SEQ_DATA_REG);
+  outb (old_seq | VGA_SEQ_CLOCK_MODE_SCROFF, VGA_SEQ_DATA_REG);
+}
+
+/* Enable the VGA video signal.  */
+static void
+display_enable (void)
+{
+  /* It isn't required to set the index, but do it just to be sure.  */
+  outb (VGA_SEQ_CLOCK_MODE_ADDR, VGA_SEQ_ADDR_REG);
+  /* Restore the sequence register to the state before the display was
+     disabled.  */
+  outb (old_seq, VGA_SEQ_DATA_REG);
+}
+
+
+struct arguments
+{
+  int powermodes;
+};
+
+const char *argp_program_version = "blank 0.1";
+static struct argp_option options[] = {
+  {"powermodes",     'p', "POWERMODES",          0,
+   "One or more of the the modes BLANK, SLEEP, STANDBY, SUSPEND, POWEROFF "
+   "(default SLEEP)" },
+  {0}
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  struct arguments *arguments = state->input;
+
+  switch (key)
+    {
+    case 'p':
+      {
+       char *args = strdupa (arg);
+       char *curarg;
+       arguments->powermodes = 0;
+      
+       curarg = strtok (args, ",");
+       while (curarg)
+         {
+           if (!strcasecmp (curarg, "BLANK"))
+             arguments->powermodes |= BLANK;
+           else if (!strcasecmp (curarg, "SLEEP"))
+             arguments->powermodes |= SLEEP;
+           else if (!strcasecmp (curarg, "STANDBY"))
+             arguments->powermodes |= STANDBY;
+           else if (!strcasecmp (curarg, "SUSPEND"))
+             arguments->powermodes |= SUSPEND;
+           else if (!strcasecmp (curarg, "POWEROFF"))
+             arguments->powermodes |= POWEROFF;
+
+           curarg = strtok (NULL, ",");
+         }
+      }
+      break;
+    case ARGP_KEY_ARG:
+      argp_usage (state);
+      break;
+    case ARGP_KEY_END:
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp argp = {options, parse_opt, 0, 0};
+
+static error_t
+blank_vga_init (void **handle, int no_exit, int argc, char *argv[], int *next)
+{
+  int lastarg;
+  struct arguments arguments;
+
+  /* If a driver is loaded after this one, stop parsing before the
+     "-d".  */
+  for (lastarg = *next; lastarg < argc; lastarg++)
+    if (!strcmp (argv[lastarg], "-d"))
+      break;
+
+  /* If this driver is the last don't parse the last argument because
+     it is an argument for the console-client.  */
+  if (lastarg == argc)
+    lastarg--;
+
+  /* By default only handle sleep.  */
+  arguments.powermodes = SLEEP;
+
+  if (lastarg > *next)
+    {
+      /* Prepare arguments for argp parsing.  */
+      int new_argc = lastarg - *next + 1;
+      char **new_argv = &argv[*next - 1];
+      char *oldarg = argv[0];
+      /* XXX: Is hardcoded.  */
+      argv[0] = "blank_vga";
+
+      argp_parse (&argp, new_argc, new_argv, 0, 0, &arguments);
+      argv[0] = oldarg;
+      *next = lastarg;
+    }
+
+  powermodes = arguments.powermodes;
+  return 0;
+}
+
+/* Start the PC keyboard driver.  */
+static error_t
+blank_vga_start (void *handle)
+{
+  error_t err;
+
+  err = driver_add_screensaver (&blank_vga_ops, NULL);
+  return err;
+}
+
+/* Make the screensaver sleep with power level LEVEL. Immediatly
+   return. */
+static void
+blank_vga_sleep (void *handle, power_level_t level)
+{
+  switch (level)
+    {
+    case pl_blank:
+      if (!(powermodes & BLANK))
+       break;
+      display_disable ();
+      break;
+    case pl_sleep:
+      if (!(powermodes & SLEEP))
+       break;
+      display_disable ();
+      break;
+    case pl_standby:
+      if (!(powermodes & STANDBY))
+       break;
+      display_disable ();
+      break;
+    case pl_suspend:
+      if (!(powermodes & SUSPEND))
+       break;
+      display_disable ();
+      break;
+    case pl_poweroff:
+      if (!(powermodes & POWEROFF))
+       break;
+      display_disable ();
+      break;
+    } 
+
+  display_status = DISPLAY_OFF;
+}
+
+/* Make the screensaver wake up.  */
+static void
+blank_vga_wakeup (void *handle)
+{
+  if (display_status == DISPLAY_OFF)
+    display_enable ();
+
+  display_status = DISPLAY_ON;
+}
+
+/* Deinitialize the PC keyboard driver.  */
+static error_t
+blank_vga_fini (void *handle, int force)
+{
+  if (display_status == DISPLAY_OFF)
+    display_enable ();
+
+  return 0;
+}
+
+struct driver_ops driver_blank_vga_ops =
+  {
+    blank_vga_init,
+    blank_vga_start,
+    blank_vga_fini
+  };
+
+static struct screensaver_ops blank_vga_ops =
+  {
+    blank_vga_sleep,
+    blank_vga_wakeup
+  };
diff -upN console-client-with_get_dim/console.c console-client/console.c
--- console-client-with_get_dim/console.c       2003-05-19 20:50:15.000000000 
+0200
+++ console-client/console.c    2003-05-19 20:32:32.000000000 +0200
@@ -1,5 +1,5 @@
 /* console.c -- A pluggable console client.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    Written by Marcus Brinkmann.
 
    This program is free software; you can redistribute it and/or
@@ -48,6 +48,187 @@ static struct mutex global_lock;
 static vcons_t active_vcons = NULL;
 
 
+static struct timer_list screensaver_timer;
+
+/* A list of screensaver timeout values for every powerlevel.  */
+static long powerlevel[HIGHEST_POWER_LEVEL + 1];
+
+/* First set powerlevel. If it has the value -1 the screensaving is
+   disabled.  */
+static power_level_t first_powerlevel = -1;
+
+/* First set powerlevel. If it has the value -1 the screensaving is
+   disabled.  */
+static power_level_t last_powerlevel = -1;
+
+/* The current powerlevel if saving, if not set to -1.  */
+static power_level_t current_powerlevel = -1;
+
+/* Bitmask of wakeup events.  */
+static int screensaver_events = EVENT_INPUT;
+
+/* The backup of the active vcons.  */
+static vcons_t screensaver_vcons;
+
+/* Start all screensavers, this function is called by the timer.  */
+static int
+start_screensaver (void *handle)
+{
+  /* XXX: A pointer is always >= int?  */
+  power_level_t pl = (power_level_t) handle;
+  power_level_t next;
+
+  mutex_lock (&global_lock);
+
+  /* Disable the virtual console if it has not been disabled yet. XXX:
+     Close it to save CPU time.  */
+  if (!screensaver_vcons)
+    {
+      screensaver_vcons = active_vcons;
+      ports_port_ref (screensaver_vcons);
+      active_vcons = NULL;
+    }
+
+  /* XXX: Switching to another screensaver (with another powerlevel)
+     shouldn't stop other screensavers?  */
+  screensaver_iterate
+    {
+      /* Wakeup the screensavers of the previous levels.  */
+      if (screensaver->ops->wakeup)
+       screensaver->ops->wakeup (screensaver->handle);
+      
+      /* XXX: Refresh the display here? Perhaps it is a bad thing to
+        lose the global lock while refreshing.  */
+
+      /* Start the screensavers for this powerlevel.  */
+      if (screensaver->ops->sleep)
+       screensaver->ops->sleep (screensaver->handle, pl);
+    }
+
+  /* XXX: Check if a screensaver was started.  */
+ 
+  /* The screensaver is running now.  */
+  current_powerlevel = pl;
+
+  /* Search for the next powerlevel.  */
+      
+  for (next = pl + 1; next <= last_powerlevel;
+       next++)
+    {
+      /* The next powerlevel should be skipped.  */
+      if (powerlevel[next] == -1)
+       continue;
+      
+      /* Activate the timer for the next powerlevel.  */
+      screensaver_timer.expires = fetch_jiffies () + 
+       (powerlevel[next] - powerlevel[pl]);
+      screensaver_timer.fnc_data = (void *) next;
+
+      mutex_unlock (&global_lock);
+      /* Enable the timer for the next powerlevel.  */
+      return 1;
+    }
+      
+  /* No next powerlevel found, keep this one running, disable the
+     timer.  */
+  mutex_unlock (&global_lock);
+  return 0;
+}
+
+/* Report the event EVENT that can possibly stop the
+   screensaver. Return 1 if this routine awakened a screensaver. Input
+   drivers should throw away the input that awakened the
+   screensaver. If the event was on the current vc set VCONS to 0,
+   otherwise set VCONS pass the locked vcons on which the event
+   happened in VCONS.  */
+int
+console_screensaver_event (screensaver_event_t event, vcons_t vcons)
+{
+  /* check if this event may stop the screensaver.  */
+  switch (event)
+    {
+    case ev_input:
+      if (!(screensaver_events & EVENT_INPUT))
+         return 0;
+      break;
+    case ev_output:
+      if (!(screensaver_events & EVENT_OUTPUT))
+         return 0;
+      break;
+    case ev_bell:
+      if (!(screensaver_events & EVENT_BELL))
+         return 0;
+      break;
+    case ev_flash:
+      if (!(screensaver_events & EVENT_FLASH))
+         return 0;
+      break;
+    }
+
+  mutex_lock (&global_lock);
+  
+  screensaver_timer.fnc_data = (void *) first_powerlevel;
+  screensaver_timer.expires = fetch_jiffies () +
+    powerlevel[first_powerlevel];
+
+  /* Check if there is a screensaver running.  */
+  if (current_powerlevel != -1)
+    {
+      /* Wakeup all screensavers.  */
+      screensaver_iterate
+       if (screensaver->ops->sleep)
+         screensaver->ops->wakeup (screensaver->handle);
+
+      /* Start the timer. It has been stopped if this was the last
+        powerlevel.  */
+      if (current_powerlevel == last_powerlevel)
+       timer_add (&screensaver_timer);
+
+      /* There is no screensaver running ATM.  */
+      current_powerlevel = -1;
+
+      /* Restore active vcons.  */
+      assert (active_vcons == NULL);
+      
+      active_vcons = screensaver_vcons;
+      screensaver_vcons = NULL;
+
+      /* The event was for the current vcons.  */
+      if (!vcons)
+       {
+         /* Refresh the screen.  */
+         vcons = active_vcons;
+         if (!vcons)
+           {
+             mutex_unlock (&global_lock);
+             return 1;
+           }
+
+         ports_port_ref (vcons);
+         mutex_unlock (&global_lock);
+         
+         mutex_lock (&vcons->lock);
+         cons_vcons_refresh (vcons);
+         mutex_unlock (&vcons->lock);
+
+         ports_port_deref (vcons);
+       }
+      else
+       {
+         mutex_unlock (&global_lock);
+         cons_vcons_refresh (vcons);
+       }
+
+      return 1;
+    }
+
+  mutex_unlock (&global_lock);
+  
+  return 0;
+}
+
+
+
 /* Callbacks for input source drivers.  */
 
 /* Switch the active console to console ID or DELTA (relative to the
@@ -194,7 +375,7 @@ cons_vcons_add (cons_t cons, vcons_list_
 {
   error_t err = 0;
   mutex_lock (&global_lock);
-  if (!active_vcons)
+  if (!active_vcons && !screensaver_vcons)
     {
       vcons_t vcons;
 
@@ -204,7 +385,10 @@ cons_vcons_add (cons_t cons, vcons_list_
       if (!err)
         {
           vcons_entry->vcons = vcons;
-          active_vcons = vcons;
+         if (current_powerlevel == -1)
+           active_vcons = vcons;
+         else
+           screensaver_vcons = vcons;
           mutex_unlock (&vcons->lock);
         }
     }
@@ -304,6 +488,8 @@ void
 cons_vcons_write (vcons_t vcons, conchar_t *str, size_t length,
                  uint32_t col, uint32_t row)
 {
+  console_screensaver_event (ev_output, vcons);
+
   mutex_lock (&global_lock);
   if (vcons == active_vcons)
     display_iterate
@@ -318,6 +504,8 @@ cons_vcons_write (vcons_t vcons, conchar
 void
 cons_vcons_beep (vcons_t vcons)
 {
+  console_screensaver_event (ev_bell, vcons);
+
   mutex_lock (&global_lock);
   if (vcons == active_vcons)
     bell_iterate
@@ -332,6 +520,8 @@ cons_vcons_beep (vcons_t vcons)
 void
 cons_vcons_flash (vcons_t vcons)
 {
+  console_screensaver_event (ev_flash, vcons);
+
   mutex_lock (&global_lock);
   if (vcons == active_vcons)
     display_iterate
@@ -361,6 +551,21 @@ options[] =
   {
     {"driver-path", 'D', "PATH", 0, "Specify search path for driver modules" },
     {"driver", 'd', "NAME", 0, "Add driver NAME to the console" },
+    {"saver-events", 'e', "EVENTS", 0, "Set the event to awake the "
+     "screensaver in EVENT. The events should one or more of: INPUT, OUTPUT, "
+     "BELL, FLASH."},
+    {0, 0, 0, 0, "Set screensaver timeouts. Screensavers are run in the "
+     "order blank, sleep, standby, suspend, poweroff."},
+    {"blank" , 'b', "SECONDS", 0, 
+     "Blank after SECONDS second", 1},
+    {"sleep" , 's', "SECONDS", 0, 
+     "Sleep after SECONDS second", 1},
+    {"standby" , 't', "SECONDS", 0, 
+     "Sleep after SECONDS second", 1},
+    {"suspend" , 'u', "SECONDS", 0, 
+     "Suspend after SECONDS second", 1},
+    {"poweroff" , 'p', "SECONDS", 0, 
+     "Poweroff after SECONDS second", 1},
     {0}
   };
 
@@ -368,8 +573,41 @@ options[] =
 static error_t
 parse_opt (int key, char *arg, struct argp_state *state)
 {
+  void set_powerlevel (power_level_t pl, int secs)
+    {
+      int i;
+      
+      secs *= 100;
+
+      /* The amount of seconds of a lower level should be less than
+        the current one.  */
+      for (i = 0; i < pl; i++)
+         if (powerlevel[i] > secs)
+           {
+             /* XXX: Display warning.  */
+             return;
+           }
+      
+      if (pl + 1 < HIGHEST_POWER_LEVEL)
+       for (i = pl + 1; i < HIGHEST_POWER_LEVEL; i++)
+         if (powerlevel[i] < secs && powerlevel[i] != -1)
+           {
+             /* XXX: Display warning.  */
+             return;
+           }
+
+      powerlevel[pl] = secs;
+      
+      if (pl < first_powerlevel || first_powerlevel == -1)
+       first_powerlevel = pl;
+
+      if (pl > last_powerlevel || last_powerlevel == -1)
+       last_powerlevel = pl;
+    }
+
   static int devcount = 0;
   error_t err;
+  int secs;
 
   switch (key)
     {
@@ -409,6 +647,56 @@ parse_opt (int key, char *arg, struct ar
       devcount++;
       break;
 
+    case 'b':
+      secs = atoi (arg);
+      set_powerlevel (pl_blank, secs);
+      break;
+      
+    case 's':
+      secs = atoi (arg);
+      set_powerlevel (pl_sleep, secs);
+      break;
+
+    case 't':
+      secs = atoi (arg);
+      set_powerlevel (pl_standby, secs);
+      break;
+      
+    case 'u':
+      secs = atoi (arg);
+      set_powerlevel (pl_suspend, secs);
+      break;
+
+    case 'p':
+      secs = atoi (arg);
+      set_powerlevel (pl_poweroff, secs);
+      break;
+
+    case 'e':
+      {
+       char *args = strdupa (arg);
+       char *curarg;
+       screensaver_events = 0;
+      
+       /* Split a comma seperated string.  */
+       curarg = strtok (args, ",");
+       while (curarg)
+         {
+           if (!strcasecmp (curarg, "INPUT"))
+             screensaver_events |= EVENT_INPUT;
+           else if (!strcasecmp (curarg, "OUTPUT"))
+             screensaver_events |= EVENT_OUTPUT;
+           else if (!strcasecmp (curarg, "BELL"))
+             screensaver_events |= EVENT_BELL;
+           else if (!strcasecmp (curarg, "FLASH"))
+             screensaver_events |= EVENT_FLASH;
+
+           curarg = strtok (NULL, ",");
+         }
+       break;
+      }
+
+
     case ARGP_KEY_SUCCESS:
       if (!devcount)
        {
@@ -434,9 +722,13 @@ main (int argc, char *argv[])
 {
   error_t err;
   char *errname;
+  power_level_t i;
 
   driver_init ();
 
+  for (i = 0; i <= HIGHEST_POWER_LEVEL; i++)
+      powerlevel[i] = -1;
+
   /* Parse our command line.  This shouldn't ever return an error.  */
   argp_parse (&startup_argp, argc, argv, 0, 0, 0);
 
@@ -460,6 +752,18 @@ main (int argc, char *argv[])
       error (1, err, "Timer thread initialization failed");
     }
 
+  /* Initialize screensaver timers.  */
+  if (first_powerlevel != -1)
+    {
+      timer_clear (&screensaver_timer);
+      screensaver_timer.fnc = start_screensaver;
+      screensaver_timer.fnc_data = (void *) first_powerlevel;
+
+      screensaver_timer.expires = fetch_jiffies () + 
+       powerlevel[first_powerlevel];
+      timer_add (&screensaver_timer);
+    }
+
   cons_server_loop ();
 
   /* Never reached.  */
diff -upN console-client-with_get_dim/driver.c console-client/driver.c
--- console-client-with_get_dim/driver.c        2003-05-19 20:50:15.000000000 
+0200
+++ console-client/driver.c     2003-05-17 01:26:12.000000000 +0200
@@ -1,5 +1,5 @@
 /* driver.c - The console client driver code.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    Written by Marcus Brinkmann.
 
    This file is part of the GNU Hurd.
@@ -56,6 +56,7 @@ driver_init (void)
   mutex_init (&display_list_lock);
   mutex_init (&input_list_lock);
   mutex_init (&bell_list_lock);
+  mutex_init (&screensaver_list_lock);
   return 0;
 }
 
@@ -85,7 +86,7 @@ driver_fini (void)
    under the given NAME (which must be unique among all loaded
    drivers) with arguments ARGZ with length ARGZ_LEN.  This funtion
    will grab the driver list lock.  The driver itself might try to
-   grab the display, input source and bell list locks as well.  */
+   grab the display, input source, bell and screensaver list locks as well.  */
 error_t driver_add (const char *const name, const char *const driver,
                    int argc, char *argv[], int *next, int start)
 {
@@ -129,7 +130,8 @@ error_t driver_add (const char *const na
       shobj = dlopen (filename, RTLD_LAZY);
       if (!shobj)
        {
-         const char *errstring = dlerror (); /* Must always call or it leaks! 
*/
+         const char *errstring = dlerror (); /* Must always call
+                                                or it leaks! */
          if (errno != ENOENT)
            {
              free (filename);
@@ -264,7 +266,7 @@ driver_start (char **name)
 
 /* Deinitialize and unload the driver with the name NAME.  This
    function will grab the driver list lock.  The driver might try to
-   grab the display, input source and bell list locks as well.  */
+   grab the display, input source, bell and screensaver list locks as well.  */
 error_t driver_remove (const char *const name)
 {
   error_t err;
@@ -351,3 +353,4 @@ driver_remove_##component (component##_o
 ADD_REMOVE_COMPONENT (display)
 ADD_REMOVE_COMPONENT (input)
 ADD_REMOVE_COMPONENT (bell)
+ADD_REMOVE_COMPONENT (screensaver)
diff -upN console-client-with_get_dim/driver.h console-client/driver.h
--- console-client-with_get_dim/driver.h        2003-05-19 20:50:15.000000000 
+0200
+++ console-client/driver.h     2003-05-17 01:26:20.000000000 +0200
@@ -1,5 +1,5 @@
 /* driver.h - The interface to and for a console client driver.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    Written by Marcus Brinkmann.
 
    This file is part of the GNU Hurd.
@@ -27,6 +27,7 @@
 #include "display.h"
 #include "input.h"
 #include "bell.h"
+#include "screensaver.h"
 
 
 /* The path where we search for drivers, in addition to the default
@@ -56,8 +57,8 @@ typedef struct driver_ops *driver_ops_t;
    under the given NAME (which must be unique among all loaded
    drivers) with arguments ARGC, ARGV and NEXT (see
    parse_startup_args).  This function will grab the driver list lock.
-   The driver itself might try to grab the display, input source and
-   bell list locks as well.  */
+   The driver itself might try to grab the display, input source, bell
+   and screensaver list locks as well.  */
 error_t driver_add (const char *const name, const char *const driver,
                    int argc, char *argv[], int *next, int start);
 
@@ -70,7 +71,8 @@ error_t driver_start (char **name);
 
 /* Deinitialize and unload the driver with the name NAME.  This
    function will grab the driver list lock.  The driver might try to
-   grab the display, input source and bell list locks as well.  */
+   grab the display, input source, bell and screensaver list locks as
+   well.  */
 error_t driver_remove (const char *const name);
 
 /* Iterate over all loaded drivers.  This macro will grab the driver
@@ -140,7 +142,7 @@ struct driver_ops
                   int argc, char *argv[], int *next);
 
   /* Activate the driver instance.  This function should load all the
-     display, input and bell river components for this driver
+     display, input, bell and screensaver driver components for this driver
      instance.
 
      If successful, the function should return zero.  In this case it
@@ -279,4 +281,36 @@ extern struct mutex bell_list_lock;
 extern bell_t bell_list;
 extern size_t bell_list_len;
 
+
+/* Iterate over all loaded screensavers.  This macro will grab the
+   screensaver list lock.  You use it with a block, just like
+   driver_iterate.
+
+   screensaver_iterate screensaver->ops->wakeup (screensaver->handle);
+
+   The variable SCREENSAVER is provided by the macro.  */
+#define screensaver_iterate                                             \
+  for (screensaver_t screensaver = (mutex_lock (&screensaver_list_lock), \
+                                   &screensaver_list[0]);               \
+       screensaver < &screensaver_list[screensaver_list_len]            \
+        || (mutex_unlock (&screensaver_list_lock), 0);                  \
+       screensaver++)
+
+
+/* The screensaver structure, needed by the macro above.  Don't use it
+   directly.  */
+struct screensaver
+{
+  screensaver_ops_t ops;
+  void *handle;
+};
+typedef struct screensaver *screensaver_t;
+
+/* Forward declarations needed by the macro above.  Don't use these
+   variables directly.  */
+extern struct mutex screensaver_list_lock;
+extern screensaver_t screensaver_list;
+extern size_t screensaver_list_len;
+
+
 #endif /* _CONSOLE_DRIVER_H_ */
diff -upN console-client-with_get_dim/life.c console-client/life.c
--- console-client-with_get_dim/life.c  1970-01-01 01:00:00.000000000 +0100
+++ console-client/life.c       2003-05-19 21:02:00.000000000 +0200
@@ -0,0 +1,442 @@
+/* life.c - Conway's game of life screensaver.
+   Copyright (C) 2003 Free Software Foundation, Inc.
+   Written by Marco Gerards.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd 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, or (at
+   your option) any later version.
+
+   The GNU Hurd 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, USA. */
+
+#include <assert.h>
+#include <sys/io.h>
+#include <argp.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "driver.h"
+
+
+/* Forward declaration.  */
+static struct screensaver_ops life_ops;
+
+/* Bitmap of supported powermodes.  */
+static int powermodes;
+
+/* Screensaver is running.  */
+static int saving = 0;
+
+
+
+/* Rules:
+   - The screen is cyclic. (The line above the top line is the lowest
+   line.
+   - A cell with 2 or 3 living neighbour will stay alife, otherwise it
+   dies.
+   - A dead cell with _exactly_ 3 living neighbours will come to life.
+*/
+
+/* XXX: All these values should be user configurable.  */
+
+/* The amount of cells that will be shown on display creation.  */
+#define        INITIAL_CELLS   300
+/* NRSTEPS defined the number of steps to wait before EXTRA_CELLS are
+   added.  */
+#define        NRSTEPS         20
+#define        EXTRA_CELLS     50
+/* Time in usec to wait between screen updates.  */
+#define        WAIT_TIME       75000
+
+/* A linked list of life_game threads.  */
+static struct life_thr
+{
+  struct life_thr *next;
+  cthread_t thr;
+} *life_threads = NULL;
+
+/* Start the game of life and use ANYDISP as output display_t.  */
+static any_t
+life_game (any_t anydisp)
+{
+  display_t display = anydisp;
+  int width;
+  int height;
+  conchar_t *screen1;
+  conchar_t *screen2;
+
+  /* Once every X steps more cells are added to prevent starvation.  */
+  int step = 0;
+  
+  /* Clear the logical screen SCREEN.  */
+  void cls (conchar_t *screen)
+    {
+      int i;
+      
+      memset (screen, 0, width * height * sizeof (conchar_t));
+      for (i = 0; i < width * height; i++)
+       {
+         screen[i].chr = ' ';
+         screen[i].attr.fgcol = CONS_COLOR_WHITE;
+       }
+    }
+
+  /* Add CELLC cells to the screen SCREEN.  */
+  void addcells (conchar_t *screen, int cellc)
+    {
+      int i;
+      for (i = 0; i < cellc; i++)
+       screen[random () % (width * height)].chr = '*';
+    }
+
+  int wrap (int i, int max)
+    {
+      if (i < 0)
+       return max + i;
+      else
+       return i % max;
+    }
+  
+  /* Return the value of the cell on position X,Y of the logical
+     screen SCREEN.  */
+  char get_cell (conchar_t *screen, int x, int y)
+    {
+      return screen[wrap (x, width) + wrap (y, height) * width].chr;
+    }
+
+  /* Set the cell on position X,Y of the logical screen SCREEN to C.  */
+  void set_cell (conchar_t *screen, int x, int y, char c)
+    {
+      screen[wrap (x, width) + wrap (y, height) * width].chr = c;    
+    }
+  
+  /* Count how many living neighbours the cell on position X,Y of
+     logical screen SCREEN has.  */
+  int living_nb (conchar_t *screen, int x, int y)
+    {
+      int cells = 0;
+        
+      if (get_cell (screen, x+1 ,y-1) == '*') cells++; 
+      if (get_cell (screen, x+1 ,y) == '*') cells++; 
+      if (get_cell (screen, x ,y+1) == '*') cells++; 
+      if (get_cell (screen, x+1 ,y+1) == '*') cells++; 
+      if (get_cell (screen, x-1 ,y) == '*') cells++; 
+      if (get_cell (screen, x ,y-1) == '*') cells++; 
+      if (get_cell (screen, x-1 ,y-1) == '*') cells++; 
+      if (get_cell (screen, x-1 ,y+1) == '*') cells++; 
+
+      return cells;
+    }
+
+  /* Show the logical screen SCREEN on the display.  */
+  void showscreen (conchar_t *screen)
+    {
+      int y;
+
+      /* Copy the screen to the display, one line at the time.  */
+      for (y = 0; y < height; y++)
+       if (display->ops->write)
+         display->ops->write (display->handle, &screen[y * width],
+                              width, 0, y);
+
+      /* Update the screen.  */
+      if (display->ops->update)
+       display->ops->update (display->handle);
+    }
+
+  if (display->ops->get_dimensions)
+    display->ops->get_dimensions (display->handle, &width, &height);
+  else
+    return 0;
+
+  screen1 = malloc (width * height * sizeof (conchar_t));
+  if (!screen1)
+    return 0;
+
+  screen2 = malloc (width * height * sizeof (conchar_t));
+  if (!screen2)
+    return 0;
+
+  /* Hide the cursor.  */
+  if (display->ops->set_cursor_status)
+    display->ops->set_cursor_status (display->handle, CONS_CURSOR_INVISIBLE);
+
+  cls (screen1);
+  addcells (screen1, INITIAL_CELLS);
+  showscreen (screen1);
+
+  while (saving)
+    {
+      conchar_t *swapscreen;
+      int x;
+      int y;
+      
+      /* Add 100 cells every 30 steps so the screensaver can continue
+        to run smoothly.  */
+      if (++step == NRSTEPS)
+       {
+         addcells (screen1, EXTRA_CELLS);
+         step = 0;
+       }
+
+      /* Swap the buffers.  */
+      swapscreen = screen1;
+      screen1 = screen2;
+      screen2 = swapscreen;
+      
+      cls (screen1);
+
+      /* Calculate the new screen.  */
+      for (x = 0; x < width; x++)
+       for (y = 0; y < height; y++)
+         {
+           int nb = living_nb (screen2, x, y);
+           char cell = get_cell (screen2, x, y);
+
+           if (nb == 3 || (cell == '*' && nb == 2))
+             set_cell (screen1, x, y, '*');
+         }
+      
+      showscreen (screen1);
+      usleep (WAIT_TIME);
+    }
+
+  /* The display must be cleared because the physical screen can be
+     larger than the VC.  */
+  cls (screen1);
+  showscreen (screen1);
+
+  free (screen1);
+  free (screen2);
+
+  return 0;
+}
+
+/* Start a life_game thread for every display.  */
+static error_t
+life_start_game (void)
+{
+  /* The amount of games that should simultaniously run.  */
+  int display_count = 0;
+
+  saving = 1;
+
+  display_iterate 
+    display_count++;
+
+  /* For every display driver another game runs because each display
+     can have a different resolution.  */
+  display_iterate
+    {
+      struct life_thr *newthr;
+
+      newthr = malloc (sizeof (struct life_thr));
+      if (!newthr)
+       return ENOMEM;
+      newthr->next = life_threads;
+      newthr->thr = cthread_fork (life_game, display);
+      life_threads = newthr;
+    }
+  
+  return 0;
+}
+
+
+
+struct arguments
+{
+  int powermodes;
+};
+
+const char *argp_program_version = "life 0.1";
+static struct argp_option options[] = {
+  {"powermodes",     'p', "POWERMODES",          0,
+   "One or more of the the modes BLANK, SLEEP, STANDBY, SUSPEND, POWEROFF"
+   "(Default BLANK)" },
+  {0}
+};
+
+static error_t
+parse_opt (int key, char *arg, struct argp_state *state)
+{
+  struct arguments *arguments = state->input;
+
+  switch (key)
+    {
+    case 'p':
+      {
+       char *args = strdupa (arg);
+       char *curarg;
+       arguments->powermodes = 0;
+      
+       /* Split a comma seperated string.  */
+       curarg = strtok (args, ",");
+       while (curarg)
+         {
+           if (!strcasecmp (curarg, "BLANK"))
+             arguments->powermodes |= BLANK;
+           else if (!strcasecmp (curarg, "SLEEP"))
+             arguments->powermodes |= SLEEP;
+           else if (!strcasecmp (curarg, "STANDBY"))
+             arguments->powermodes |= STANDBY;
+           else if (!strcasecmp (curarg, "SUSPEND"))
+             arguments->powermodes |= SUSPEND;
+           else if (!strcasecmp (curarg, "POWEROFF"))
+             arguments->powermodes |= POWEROFF;
+
+           curarg = strtok (NULL, ",");
+         }
+      }
+      break;
+    case ARGP_KEY_ARG:
+      argp_usage (state);
+      break;
+    case ARGP_KEY_END:
+      break;
+    default:
+      return ARGP_ERR_UNKNOWN;
+    }
+  return 0;
+}
+
+static struct argp argp = {options, parse_opt, 0, 0};
+
+
+static error_t
+life_init (void **handle, int no_exit, int argc, char *argv[], int *next)
+{
+  int lastarg;
+  struct arguments arguments;
+
+  /* FIXME: argp is reentrant(!?).  */
+
+  /* If a driver is loaded after this one, stop parsing before the
+     "-d".  */
+  for (lastarg = *next; lastarg < argc; lastarg++)
+    if (!strcmp (argv[lastarg], "-d"))
+      break;
+
+  /* If this driver is the last don't parse the last argument because
+     it is an argument for the console-client.  */
+  if (lastarg == argc)
+    lastarg--;
+
+  /* By default only handle sleep and blank.  */
+  arguments.powermodes = BLANK;
+
+  if (lastarg  > *next)
+    {
+      /* Prepare arguments for argp parsing.  */
+      int new_argc = lastarg - *next + 1;
+      char **new_argv = &argv[*next - 1];
+      char *oldarg = argv[0];
+      /* XXX: Is hardcoded.  */
+      argv[0] = "life";
+
+      argp_parse (&argp, new_argc, new_argv, 0, 0, &arguments);
+      argv[0] = oldarg;
+      *next = lastarg;
+    }
+
+  powermodes = arguments.powermodes;
+  return 0;
+}
+
+/* Start the screensaver driver.  */
+static error_t
+life_start (void *handle)
+{
+  error_t err;
+
+  err = driver_add_screensaver (&life_ops, NULL);
+  return err;
+}
+
+/* Make the screensaver sleep with power level LEVEL. Immediatly
+   return. */
+static void
+life_sleep (void *handle, power_level_t level)
+{
+  switch (level)
+    {
+    case pl_blank:
+      if (!(powermodes & BLANK))
+       break;
+      life_start_game ();
+      break;
+    case pl_sleep:
+      if (!(powermodes & SLEEP))
+       break;
+      life_start_game ();
+      break;
+    case pl_standby:
+      if (!(powermodes & STANDBY))
+       break;
+      life_start_game ();
+      break;
+    case pl_suspend:
+      if (!(powermodes & SUSPEND))
+       break;
+      life_start_game ();
+      break;
+    case pl_poweroff:
+      if (!(powermodes & POWEROFF))
+       break;
+      life_start_game ();
+      break;
+    }
+}
+
+/* Make the screensaver wake up.  */
+static void
+life_wakeup (void *handle)
+{
+  struct life_thr *thr = life_threads;
+
+  /* Can't wakeup if already awake.  */
+  if (!saving)
+    return;
+
+  /* Wakeup all life_game threads.  */
+  saving = 0;
+
+  /* Synchronise.  */
+  while (thr)
+    {
+      struct life_thr *old = thr;
+      cthread_join (thr->thr);
+      thr = thr->next;
+      free (old);
+    }
+  life_threads = NULL;
+}
+
+/* Deinitialize the screensaver driver.  */
+static error_t
+life_fini (void *handle, int force)
+{
+  life_wakeup (handle);
+  return 0;
+}
+
+struct driver_ops driver_life_ops =
+  {
+    life_init,
+    life_start,
+    life_fini
+  };
+
+static struct screensaver_ops life_ops =
+  {
+    life_sleep,
+    life_wakeup
+  };
diff -upN console-client-with_get_dim/Makefile console-client/Makefile
--- console-client-with_get_dim/Makefile        2003-05-19 20:50:15.000000000 
+0200
+++ console-client/Makefile     2003-05-17 17:51:04.000000000 +0200
@@ -41,11 +41,14 @@ driver-CPPFLAGS = -D'CONSOLE_DEFPATH="$(
 console: ../libcons/libcons.a ../libports/libports.a \
        ../libthreads/libthreads.a ../libshouldbeinlibc/libshouldbeinlibc.a
 
-modules = vga pc_kbd generic_speaker
+modules = vga pc_kbd generic_speaker blank blank_vga life
 
 vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,bdf.c vga-dynafont.c \
        vga-dynacolor.c vga-support.c vga.c)
 pc_kbd.so.$(hurd-version): $(patsubst %.c,%_pic.o,pc-kbd.c)
+blank.so.$(hurd-version): $(patsubst %.c,%_pic.o,blank.c)
+blank_vga.so.$(hurd-version): $(patsubst %.c,%_pic.o,blank_vga.c)
+life.so.$(hurd-version): $(patsubst %.c,%_pic.o,life.c)
 generic_speaker.so.$(hurd-version): $(patsubst %.c,%_pic.o,generic-speaker.c)
 
 ifneq ($(LIBNCURSESW),)
diff -upN console-client-with_get_dim/pc-kbd.c console-client/pc-kbd.c
--- console-client-with_get_dim/pc-kbd.c        2003-05-19 20:50:15.000000000 
+0200
+++ console-client/pc-kbd.c     2003-05-19 20:09:40.000000000 +0200
@@ -1,5 +1,5 @@
 /* pc-kbd.c - The PC Keyboard input driver.
-   Copyright (C) 2002 Free Software Foundation, Inc.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
    Written by Marcus Brinkmann.
 
    This file is part of the GNU Hurd.
@@ -1066,7 +1066,9 @@ input_loop (any_t unused)
       else if (state.extended == 3)
        state.extended = 0;
       
-      if (size)
+      /* input_next returned with input, set an event to the
+        screensaver.  */
+      if (!console_screensaver_event (ev_input, 0) && size)
        console_input (buf, size);
     }
   return 0;
diff -upN console-client-with_get_dim/screensaver.h console-client/screensaver.h
--- console-client-with_get_dim/screensaver.h   1970-01-01 01:00:00.000000000 
+0100
+++ console-client/screensaver.h        2003-05-19 21:05:30.000000000 +0200
@@ -0,0 +1,106 @@
+/* screensaver.h - The interface to and for a screensaver driver.
+   Copyright (C) 2002, 2003 Free Software Foundation, Inc.
+   Written by Marcus Brinkmann.
+   Modified for the screensaver interface by Marco Gerards.
+
+   This file is part of the GNU Hurd.
+
+   The GNU Hurd 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, or (at
+   your option) any later version.
+
+   The GNU Hurd 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, USA. */
+
+#ifndef _SCREENSAVER_H_
+#define _SCREENSAVER_H_ 1
+
+#include <errno.h>
+
+
+/* The screensaver drivers are set up by the driver's initialization
+   routine and added to the console client with
+   driver_add_screensaver.  All subsequent operations on the display
+   are fully synchronized by the caller.  The driver deinitialization
+   routine should call driver_remove_screensaver.  */
+
+/* Forward declaration.  */
+struct screensaver_ops;
+typedef struct screensaver_ops *screensaver_ops_t;
+
+/* Add the screensaver HANDLE with the operations OPS to the console
+   client. As soon as this is called, operations on this screensaver
+   may be performed, even before the function returns.  */
+error_t driver_add_screensaver (screensaver_ops_t ops, void *handle);
+
+/* Remove the screensaver HANDLE with the operations OPS from the
+   console client.  As soon as this function returns, no operations
+   will be performed on the screensaver anymore.  */
+error_t driver_remove_screensaver (screensaver_ops_t ops, void *handle);
+
+
+/* Events that can possibly wakeup a screensaver.  */
+enum screensaver_event
+  {
+    ev_input,
+    ev_output,
+    ev_bell,
+    ev_flash,
+  };
+
+typedef enum screensaver_event screensaver_event_t;
+
+#define        EVENT_INPUT             1
+#define        EVENT_OUTPUT            2
+#define        EVENT_BELL              4
+#define        EVENT_FLASH             8
+
+/* Report the event EVENT that can possibly stop the
+   screensaver. Return 1 if this routine awakened a screensaver. Input
+   drivers should throw away the input that awakened the
+   screensaver. If the event was on the current vc set VCONS to 0,
+   otherwise set VCONS pass the locked vcons on which the event
+   happened in VCONS.  */
+int console_screensaver_event (screensaver_event_t event, vcons_t vcons);
+
+
+enum power_level
+  {
+    pl_blank,
+    pl_sleep,
+    pl_standby,
+    pl_suspend,
+    pl_poweroff
+  };
+
+typedef enum power_level power_level_t;
+
+#define        HIGHEST_POWER_LEVEL     pl_poweroff
+
+/* Powermodes to set in a bitfield.  */
+#define        BLANK           1
+#define        SLEEP           2
+#define        STANDBY         4
+#define        SUSPEND         8
+#define        POWEROFF        16
+
+struct screensaver_ops
+{
+  /* Make the screensaver sleep with power level LEVEL. immediatly
+     return.  */
+  void (*sleep) (void *handle, power_level_t level);
+
+  /* Make the screensaver wake up. Restore the display as much as is
+     possible. The console will be refreshed after the waking up the
+     last powerlevel.  */
+  void (*wakeup) (void *handle);
+};
+
+#endif /* _SCREENSAVER_H_ */




reply via email to

[Prev in Thread] Current Thread [Next in Thread]