This commit is contained in:
rhp 2001-05-31 03:30:58 +00:00
parent 287b6b15d3
commit 1785975f38
9 changed files with 320 additions and 24 deletions

View File

@ -60,6 +60,7 @@ meta_display_open (const char *name)
{
MetaDisplay *display;
Display *xdisplay;
GSList *screens;
int i;
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
@ -72,28 +73,49 @@ meta_display_open (const char *name)
XDisplayName (name));
return FALSE;
}
display = g_new (MetaDisplay, 1);
display = g_new (MetaDisplay, 1);
display->name = g_strdup (XDisplayName (name));
display->xdisplay = xdisplay;
display->error_traps = NULL;
/* we have to go ahead and do this so error handlers work */
all_displays = g_slist_prepend (all_displays, display);
screens = NULL;
i = 0;
while (i < ScreenCount (xdisplay))
{
MetaScreen *screen;
screen = meta_screen_new (display, i);
if (screen)
screens = g_slist_prepend (screens, screen);
++i;
}
if (screens == NULL)
{
/* This would typically happen because all the screens already
* have window managers
*/
XCloseDisplay (xdisplay);
all_displays = g_slist_remove (all_displays, display);
g_free (display->name);
g_free (display);
return FALSE;
}
display->screens = screens;
display->events = meta_event_queue_new (display->xdisplay,
event_queue_callback,
display);
display->window_ids = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
all_displays = g_slist_prepend (all_displays, display);
display->screens = NULL;
i = 0;
while (i < ScreenCount (xdisplay))
{
display->screens = g_slist_prepend (display->screens,
meta_screen_new (display, i));
++i;
}
return TRUE;
}
@ -110,6 +132,9 @@ free_window (gpointer key, gpointer value, gpointer data)
void
meta_display_close (MetaDisplay *display)
{
if (display->error_traps)
meta_bug ("Display closed with error traps pending\n");
g_hash_table_foreach (display->window_ids,
free_window,
NULL);
@ -126,7 +151,7 @@ meta_display_close (MetaDisplay *display)
if (all_displays == NULL)
{
meta_verbose ("Last display closed, quitting\n");
meta_verbose ("Last display closed, exiting\n");
meta_quit (META_EXIT_SUCCESS);
}
}
@ -151,6 +176,25 @@ meta_display_screen_for_root (MetaDisplay *display,
return NULL;
}
MetaDisplay*
meta_display_for_x_display (Display *xdisplay)
{
GSList *tmp;
tmp = all_displays;
while (tmp != NULL)
{
MetaDisplay *display = tmp->data;
if (display->xdisplay == xdisplay)
return display;
tmp = tmp->next;
}
return NULL;
}
static gboolean dump_events = TRUE;
static void

View File

@ -39,6 +39,7 @@ struct _MetaDisplay
MetaEventQueue *events;
GSList *screens;
GHashTable *window_ids;
GSList *error_traps;
};
gboolean meta_display_open (const char *name);
@ -51,6 +52,6 @@ MetaWindow* meta_display_lookup_window (MetaDisplay *display,
void meta_display_register_window (MetaDisplay *display,
MetaWindow *window);
MetaDisplay* meta_display_for_x_display (Display *xdisplay);
#endif

153
src/errors.c Normal file
View File

@ -0,0 +1,153 @@
/* Metacity X error handling */
/*
* Copyright (C) 2001 Havoc Pennington, error trapping inspired by GDK
* code copyrighted by the GTK team.
*
* 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.
*/
#include "errors.h"
#include <errno.h>
typedef struct _ErrorTrap ErrorTrap;
struct _ErrorTrap
{
int error_code;
};
static int x_error_handler (Display *display,
XErrorEvent *error);
static int x_io_error_handler (Display *display);
void
meta_errors_init (void)
{
XSetErrorHandler (x_error_handler);
XSetIOErrorHandler (x_io_error_handler);
}
void
meta_error_trap_push (MetaDisplay *display)
{
ErrorTrap *et;
et = g_new (ErrorTrap, 1);
et->error_code = Success;
display->error_traps = g_slist_prepend (display->error_traps, et);
}
int
meta_error_trap_pop (MetaDisplay *display)
{
int result;
ErrorTrap *et;
GSList *next;
if (display->error_traps == NULL)
meta_bug ("No error trap to pop\n");
XSync (display->xdisplay, False);
et = display->error_traps->data;
result = et->error_code;
next = display->error_traps->next;
g_slist_free_1 (display->error_traps);
display->error_traps = next;
g_free (et);
return result;
}
static int
x_error_handler (Display *xdisplay,
XErrorEvent *error)
{
if (error->error_code)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display == NULL)
meta_bug ("Error received for unknown display?\n");
if (display->error_traps == NULL)
{
gchar buf[64];
XGetErrorText (xdisplay, error->error_code, buf, 63);
meta_fatal ("Received an X Window System error without handling it.\n"
"The error was '%s'.\n"
" (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
buf,
error->serial,
error->error_code,
error->request_code,
error->minor_code);
}
else
{
ErrorTrap *et;
et = display->error_traps->data;
et->error_code = error->error_code;
}
}
return 0;
}
static int
x_io_error_handler (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display == NULL)
meta_bug ("Error received for unknown display?\n");
if (errno == EPIPE)
{
meta_warning (_("Lost connection to the display '%s';\n"
"most likely the X server was shut down or you killed/destroyed\n"
"the window manager.\n"),
display->name);
}
else
{
meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
errno, g_strerror (errno),
display->name);
}
meta_display_close (display);
/* I believe Xlib will force an exit after we return, which
* seems sort of broken to me, but if true we should probably just
* exit for ourselves. But for now I'm not doing it.
*/
return 0;
}

33
src/errors.h Normal file
View File

@ -0,0 +1,33 @@
/* Metacity X error handling */
/*
* Copyright (C) 2001 Havoc Pennington
*
* 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.
*/
#ifndef META_ERRORS_H
#define META_ERRORS_H
#include "util.h"
#include "display.h"
void meta_errors_init (void);
void meta_error_trap_push (MetaDisplay *display);
/* returns X error code, or 0 for no error */
int meta_error_trap_pop (MetaDisplay *display);
#endif

View File

@ -22,6 +22,7 @@
#include "main.h"
#include "util.h"
#include "display.h"
#include "errors.h"
#include <stdlib.h>
@ -33,6 +34,8 @@ main (int argc, char **argv)
{
meta_main_loop = g_main_loop_new (NULL, FALSE);
meta_errors_init ();
if (!meta_display_open (NULL))
meta_exit (META_EXIT_ERROR);

5
src/run-metacity.sh Executable file
View File

@ -0,0 +1,5 @@
#! /bin/bash
Xnest :1 -scrns 2 -geometry 200x200 &
sleep 1
DISPLAY=:1 unst ./metacity

View File

@ -20,26 +20,59 @@
*/
#include "screen.h"
#include "util.h"
#include "errors.h"
MetaScreen*
meta_screen_new (MetaDisplay *display,
int number)
{
MetaScreen *screen;
Window xroot;
Display *xdisplay;
meta_verbose ("Adding screen %d on display '%s'\n", number, display->name);
/* Only display->name, display->xdisplay, and display->error_traps
* can really be used in this function, since normally screens are
* created from the MetaDisplay constructor
*/
xdisplay = display->xdisplay;
meta_verbose ("Trying screen %d on display '%s'\n",
number, display->name);
xroot = RootWindow (xdisplay, number);
/* FVWM checks for None here, I don't know if this
* ever actually happens
*/
if (xroot == None)
{
meta_warning (_("Screen %d on display '%s' is invalid\n"),
number, display->name);
return NULL;
}
/* Select our root window events */
meta_error_trap_push (display);
XSelectInput (xdisplay,
xroot,
SubstructureRedirectMask | SubstructureNotifyMask |
ColormapChangeMask | PropertyChangeMask |
LeaveWindowMask | EnterWindowMask |
ButtonPressMask | ButtonReleaseMask);
if (meta_error_trap_pop (display) != Success)
{
meta_warning (_("Screen %d on display '%s' already has a window manager\n"),
number, display->name);
return NULL;
}
screen = g_new (MetaScreen, 1);
screen->display = display;
screen->display = NULL;
screen->number = number;
screen->xscreen = ScreenOfDisplay (display->xdisplay, number);
screen->xroot = RootWindow (display->xdisplay, number);
/* Select our root window events */
XSelectInput (display->xdisplay,
screen->xroot,
SubstructureNotifyMask);
screen->xscreen = ScreenOfDisplay (xdisplay, number);
screen->xroot = xroot;
return screen;
}

View File

@ -23,6 +23,7 @@
#include "main.h"
#include <stdio.h>
#include <stdlib.h>
static gboolean is_verbose = TRUE;
@ -80,6 +81,27 @@ meta_verbose (const char *format, ...)
g_free (str);
}
void
meta_bug (const char *format, ...)
{
va_list args;
gchar *str;
g_return_if_fail (format != NULL);
va_start (args, format);
str = g_strdup_vprintf (format, args);
va_end (args);
fputs ("Bug in window manager: ", stderr);
fputs (str, stderr);
g_free (str);
/* stop us in a debugger */
abort ();
}
void
meta_warning (const char *format, ...)
{

View File

@ -31,6 +31,8 @@ void meta_debug_spew (const char *format,
...) G_GNUC_PRINTF (1, 2);
void meta_verbose (const char *format,
...) G_GNUC_PRINTF (1, 2);
void meta_bug (const char *format,
...) G_GNUC_PRINTF (1, 2);
void meta_warning (const char *format,
...) G_GNUC_PRINTF (1, 2);
void meta_fatal (const char *format,