...
This commit is contained in:
parent
287b6b15d3
commit
1785975f38
@ -60,6 +60,7 @@ meta_display_open (const char *name)
|
|||||||
{
|
{
|
||||||
MetaDisplay *display;
|
MetaDisplay *display;
|
||||||
Display *xdisplay;
|
Display *xdisplay;
|
||||||
|
GSList *screens;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
|
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
|
||||||
@ -72,28 +73,49 @@ meta_display_open (const char *name)
|
|||||||
XDisplayName (name));
|
XDisplayName (name));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
display = g_new (MetaDisplay, 1);
|
|
||||||
|
|
||||||
|
display = g_new (MetaDisplay, 1);
|
||||||
|
|
||||||
display->name = g_strdup (XDisplayName (name));
|
display->name = g_strdup (XDisplayName (name));
|
||||||
display->xdisplay = xdisplay;
|
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,
|
display->events = meta_event_queue_new (display->xdisplay,
|
||||||
event_queue_callback,
|
event_queue_callback,
|
||||||
display);
|
display);
|
||||||
|
|
||||||
display->window_ids = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,6 +132,9 @@ free_window (gpointer key, gpointer value, gpointer data)
|
|||||||
void
|
void
|
||||||
meta_display_close (MetaDisplay *display)
|
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,
|
g_hash_table_foreach (display->window_ids,
|
||||||
free_window,
|
free_window,
|
||||||
NULL);
|
NULL);
|
||||||
@ -126,7 +151,7 @@ meta_display_close (MetaDisplay *display)
|
|||||||
|
|
||||||
if (all_displays == NULL)
|
if (all_displays == NULL)
|
||||||
{
|
{
|
||||||
meta_verbose ("Last display closed, quitting\n");
|
meta_verbose ("Last display closed, exiting\n");
|
||||||
meta_quit (META_EXIT_SUCCESS);
|
meta_quit (META_EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -151,6 +176,25 @@ meta_display_screen_for_root (MetaDisplay *display,
|
|||||||
return NULL;
|
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 gboolean dump_events = TRUE;
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -39,6 +39,7 @@ struct _MetaDisplay
|
|||||||
MetaEventQueue *events;
|
MetaEventQueue *events;
|
||||||
GSList *screens;
|
GSList *screens;
|
||||||
GHashTable *window_ids;
|
GHashTable *window_ids;
|
||||||
|
GSList *error_traps;
|
||||||
};
|
};
|
||||||
|
|
||||||
gboolean meta_display_open (const char *name);
|
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,
|
void meta_display_register_window (MetaDisplay *display,
|
||||||
MetaWindow *window);
|
MetaWindow *window);
|
||||||
|
|
||||||
|
MetaDisplay* meta_display_for_x_display (Display *xdisplay);
|
||||||
|
|
||||||
#endif
|
#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 "main.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "display.h"
|
#include "display.h"
|
||||||
|
#include "errors.h"
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -33,6 +34,8 @@ main (int argc, char **argv)
|
|||||||
{
|
{
|
||||||
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
meta_main_loop = g_main_loop_new (NULL, FALSE);
|
||||||
|
|
||||||
|
meta_errors_init ();
|
||||||
|
|
||||||
if (!meta_display_open (NULL))
|
if (!meta_display_open (NULL))
|
||||||
meta_exit (META_EXIT_ERROR);
|
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 "screen.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "errors.h"
|
||||||
|
|
||||||
MetaScreen*
|
MetaScreen*
|
||||||
meta_screen_new (MetaDisplay *display,
|
meta_screen_new (MetaDisplay *display,
|
||||||
int number)
|
int number)
|
||||||
{
|
{
|
||||||
MetaScreen *screen;
|
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 = g_new (MetaScreen, 1);
|
||||||
|
|
||||||
screen->display = display;
|
screen->display = NULL;
|
||||||
screen->number = number;
|
screen->number = number;
|
||||||
screen->xscreen = ScreenOfDisplay (display->xdisplay, number);
|
screen->xscreen = ScreenOfDisplay (xdisplay, number);
|
||||||
screen->xroot = RootWindow (display->xdisplay, number);
|
screen->xroot = xroot;
|
||||||
|
|
||||||
/* Select our root window events */
|
|
||||||
XSelectInput (display->xdisplay,
|
|
||||||
screen->xroot,
|
|
||||||
SubstructureNotifyMask);
|
|
||||||
|
|
||||||
return screen;
|
return screen;
|
||||||
}
|
}
|
||||||
|
22
src/util.c
22
src/util.c
@ -23,6 +23,7 @@
|
|||||||
#include "main.h"
|
#include "main.h"
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
static gboolean is_verbose = TRUE;
|
static gboolean is_verbose = TRUE;
|
||||||
|
|
||||||
@ -80,6 +81,27 @@ meta_verbose (const char *format, ...)
|
|||||||
g_free (str);
|
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
|
void
|
||||||
meta_warning (const char *format, ...)
|
meta_warning (const char *format, ...)
|
||||||
{
|
{
|
||||||
|
@ -31,6 +31,8 @@ void meta_debug_spew (const char *format,
|
|||||||
...) G_GNUC_PRINTF (1, 2);
|
...) G_GNUC_PRINTF (1, 2);
|
||||||
void meta_verbose (const char *format,
|
void meta_verbose (const char *format,
|
||||||
...) G_GNUC_PRINTF (1, 2);
|
...) G_GNUC_PRINTF (1, 2);
|
||||||
|
void meta_bug (const char *format,
|
||||||
|
...) G_GNUC_PRINTF (1, 2);
|
||||||
void meta_warning (const char *format,
|
void meta_warning (const char *format,
|
||||||
...) G_GNUC_PRINTF (1, 2);
|
...) G_GNUC_PRINTF (1, 2);
|
||||||
void meta_fatal (const char *format,
|
void meta_fatal (const char *format,
|
||||||
|
Loading…
Reference in New Issue
Block a user