...
This commit is contained in:
parent
287b6b15d3
commit
1785975f38
@ -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
|
||||
|
@ -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
153
src/errors.c
Normal 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
33
src/errors.h
Normal 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
|
@ -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
5
src/run-metacity.sh
Executable file
@ -0,0 +1,5 @@
|
||||
#! /bin/bash
|
||||
|
||||
Xnest :1 -scrns 2 -geometry 200x200 &
|
||||
sleep 1
|
||||
DISPLAY=:1 unst ./metacity
|
51
src/screen.c
51
src/screen.c
@ -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;
|
||||
}
|
||||
|
22
src/util.c
22
src/util.c
@ -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, ...)
|
||||
{
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user