mutter/src/display.c

548 lines
13 KiB
C
Raw Normal View History

2001-05-30 11:36:31 -04:00
/* Metacity X display handler */
/*
* 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.
*/
#include "display.h"
#include "util.h"
#include "main.h"
#include "screen.h"
#include "window.h"
static GSList *all_displays = NULL;
static void meta_spew_event (MetaDisplay *display,
XEvent *event);
static void event_queue_callback (MetaEventQueue *queue,
XEvent *event,
gpointer data);
static gint
unsigned_long_equal (gconstpointer v1,
gconstpointer v2)
{
return *((const gulong*) v1) == *((const gulong*) v2);
}
static guint
unsigned_long_hash (gconstpointer v)
{
gulong val = * (const gulong *) v;
/* I'm not sure this works so well. */
#if G_SIZEOF_LONG > 4
return (guint) (val ^ (val >> 32));
#else
return val;
#endif
}
gboolean
meta_display_open (const char *name)
{
MetaDisplay *display;
Display *xdisplay;
2001-05-30 23:30:58 -04:00
GSList *screens;
2001-05-31 02:42:58 -04:00
GSList *tmp;
2001-05-30 11:36:31 -04:00
int i;
2001-06-02 00:14:18 -04:00
char *atom_names[] = { "_NET_WM_NAME" };
Atom atoms[G_N_ELEMENTS(atom_names)];
2001-05-30 11:36:31 -04:00
meta_verbose ("Opening display '%s'\n", XDisplayName (name));
xdisplay = XOpenDisplay (name);
if (xdisplay == NULL)
{
meta_warning (_("Failed to open X Window System display '%s'\n"),
XDisplayName (name));
return FALSE;
}
2001-05-31 02:42:58 -04:00
if (meta_is_syncing ())
XSynchronize (xdisplay, True);
2001-05-30 23:30:58 -04:00
display = g_new (MetaDisplay, 1);
2001-05-30 11:36:31 -04:00
display->name = g_strdup (XDisplayName (name));
display->xdisplay = xdisplay;
2001-05-30 23:30:58 -04:00
display->error_traps = NULL;
2001-05-30 11:36:31 -04:00
2001-05-30 23:30:58 -04:00
/* we have to go ahead and do this so error handlers work */
2001-05-30 11:36:31 -04:00
all_displays = g_slist_prepend (all_displays, display);
2001-05-30 23:30:58 -04:00
screens = NULL;
2001-05-30 11:36:31 -04:00
i = 0;
while (i < ScreenCount (xdisplay))
{
2001-05-30 23:30:58 -04:00
MetaScreen *screen;
screen = meta_screen_new (display, i);
if (screen)
screens = g_slist_prepend (screens, screen);
2001-05-30 11:36:31 -04:00
++i;
}
2001-05-30 23:30:58 -04:00
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);
2001-05-31 02:42:58 -04:00
display->server_grab_count = 0;
2001-06-02 00:14:18 -04:00
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
display->atom_net_wm_name = atoms[0];
2001-05-31 02:42:58 -04:00
/* Now manage all existing windows */
tmp = display->screens;
while (tmp != NULL)
{
meta_screen_manage_all_windows (tmp->data);
tmp = tmp->next;
}
2001-05-30 11:36:31 -04:00
return TRUE;
}
static void
free_window (gpointer key, gpointer value, gpointer data)
{
MetaWindow *window;
window = value;
meta_window_free (window);
}
void
meta_display_close (MetaDisplay *display)
{
2001-05-30 23:30:58 -04:00
if (display->error_traps)
meta_bug ("Display closed with error traps pending\n");
2001-05-30 11:36:31 -04:00
g_hash_table_foreach (display->window_ids,
free_window,
NULL);
g_hash_table_destroy (display->window_ids);
meta_event_queue_free (display->events);
XCloseDisplay (display->xdisplay);
g_free (display->name);
all_displays = g_slist_remove (all_displays, display);
g_free (display);
if (all_displays == NULL)
{
2001-05-30 23:30:58 -04:00
meta_verbose ("Last display closed, exiting\n");
2001-05-30 11:36:31 -04:00
meta_quit (META_EXIT_SUCCESS);
}
}
MetaScreen*
meta_display_screen_for_root (MetaDisplay *display,
Window xroot)
{
GSList *tmp;
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
if (xroot == screen->xroot)
return screen;
tmp = tmp->next;
}
return NULL;
}
2001-05-31 23:00:01 -04:00
MetaScreen*
meta_display_screen_for_x_screen (MetaDisplay *display,
Screen *xscreen)
{
GSList *tmp;
tmp = display->screens;
while (tmp != NULL)
{
MetaScreen *screen = tmp->data;
if (xscreen == screen->xscreen)
return screen;
tmp = tmp->next;
}
return NULL;
}
2001-05-31 02:42:58 -04:00
/* Grab/ungrab routines taken from fvwm */
void
meta_display_grab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
{
XSync (display->xdisplay, False);
XGrabServer (display->xdisplay);
}
XSync (display->xdisplay, False);
display->server_grab_count += 1;
}
void
meta_display_ungrab (MetaDisplay *display)
{
if (display->server_grab_count == 0)
meta_bug ("Ungrabbed non-grabbed server\n");
display->server_grab_count -= 1;
if (display->server_grab_count == 0)
{
XUngrabServer (display->xdisplay);
}
XSync (display->xdisplay, False);
}
2001-05-30 23:30:58 -04:00
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;
}
2001-05-31 02:42:58 -04:00
GSList*
meta_displays_list (void)
{
return all_displays;
}
2001-05-30 11:36:31 -04:00
static gboolean dump_events = TRUE;
static void
event_queue_callback (MetaEventQueue *queue,
XEvent *event,
gpointer data)
{
MetaWindow *window;
MetaDisplay *display;
2001-05-31 02:42:58 -04:00
gboolean is_root;
2001-05-30 11:36:31 -04:00
display = data;
if (dump_events)
meta_spew_event (display, event);
2001-05-31 02:42:58 -04:00
is_root = meta_display_screen_for_root (display, event->xany.window) != NULL;
window = NULL;
if (!is_root)
2001-05-30 11:36:31 -04:00
{
2001-05-31 02:42:58 -04:00
if (window == NULL)
window = meta_display_lookup_x_window (display, event->xany.window);
if (window != NULL)
{
if (meta_window_event (window, event))
return;
}
2001-05-30 11:36:31 -04:00
}
switch (event->type)
{
case KeyPress:
break;
case KeyRelease:
break;
case ButtonPress:
break;
case ButtonRelease:
break;
case MotionNotify:
break;
case EnterNotify:
break;
case LeaveNotify:
break;
case FocusIn:
break;
case FocusOut:
break;
case KeymapNotify:
break;
case Expose:
break;
case GraphicsExpose:
break;
case NoExpose:
break;
case VisibilityNotify:
break;
case CreateNotify:
break;
case DestroyNotify:
break;
case UnmapNotify:
break;
case MapNotify:
break;
case MapRequest:
2001-05-31 02:42:58 -04:00
if (is_root && !event->xmap.override_redirect)
{
/* Window requested mapping. Manage it if we haven't. Note that
* meta_window_new() can return NULL
*/
window = meta_display_lookup_x_window (display,
event->xmaprequest.window);
if (window == NULL)
window = meta_window_new (display, event->xmaprequest.window);
}
2001-05-30 11:36:31 -04:00
break;
case ReparentNotify:
break;
case ConfigureNotify:
break;
case ConfigureRequest:
break;
case GravityNotify:
break;
case ResizeRequest:
break;
case CirculateNotify:
break;
case CirculateRequest:
break;
case PropertyNotify:
break;
case SelectionClear:
break;
case SelectionRequest:
break;
case SelectionNotify:
break;
case ColormapNotify:
break;
case ClientMessage:
break;
case MappingNotify:
break;
default:
break;
}
}
static void
meta_spew_event (MetaDisplay *display,
XEvent *event)
{
const char *name = NULL;
char *extra = NULL;
char *winname;
MetaScreen *screen;
switch (event->type)
{
case KeyPress:
name = "KeyPress";
break;
case KeyRelease:
name = "KeyRelease";
break;
case ButtonPress:
name = "ButtonPress";
break;
case ButtonRelease:
name = "ButtonRelease";
break;
case MotionNotify:
name = "MotionNotify";
break;
case EnterNotify:
name = "EnterNotify";
break;
case LeaveNotify:
name = "LeaveNotify";
break;
case FocusIn:
name = "FocusIn";
break;
case FocusOut:
name = "FocusOut";
break;
case KeymapNotify:
name = "KeymapNotify";
break;
case Expose:
name = "Expose";
break;
case GraphicsExpose:
name = "GraphicsExpose";
break;
case NoExpose:
name = "NoExpose";
break;
case VisibilityNotify:
name = "VisibilityNotify";
break;
case CreateNotify:
name = "CreateNotify";
break;
case DestroyNotify:
name = "DestroyNotify";
break;
case UnmapNotify:
name = "UnmapNotify";
break;
case MapNotify:
name = "MapNotify";
break;
case MapRequest:
name = "MapRequest";
break;
case ReparentNotify:
name = "ReparentNotify";
break;
case ConfigureNotify:
name = "ConfigureNotify";
extra = g_strdup_printf ("x: %d y: %d w: %d h: %d above: 0x%lx",
event->xconfigure.x,
event->xconfigure.y,
event->xconfigure.width,
event->xconfigure.height,
event->xconfigure.above);
break;
case ConfigureRequest:
name = "ConfigureRequest";
break;
case GravityNotify:
name = "GravityNotify";
break;
case ResizeRequest:
name = "ResizeRequest";
break;
case CirculateNotify:
name = "CirculateNotify";
break;
case CirculateRequest:
name = "CirculateRequest";
break;
case PropertyNotify:
name = "PropertyNotify";
break;
case SelectionClear:
name = "SelectionClear";
break;
case SelectionRequest:
name = "SelectionRequest";
break;
case SelectionNotify:
name = "SelectionNotify";
break;
case ColormapNotify:
name = "ColormapNotify";
break;
case ClientMessage:
name = "ClientMessage";
break;
case MappingNotify:
name = "MappingNotify";
break;
default:
name = "Unknown";
break;
}
screen = meta_display_screen_for_root (display, event->xany.window);
if (screen)
winname = g_strdup_printf ("root %d", screen->number);
else
winname = g_strdup_printf ("0x%lx", event->xany.window);
meta_verbose ("%s on %s%s %s\n", name, winname,
extra ? ":" : "", extra ? extra : "");
g_free (winname);
if (extra)
g_free (extra);
}
MetaWindow*
2001-05-31 02:42:58 -04:00
meta_display_lookup_x_window (MetaDisplay *display,
Window xwindow)
2001-05-30 11:36:31 -04:00
{
return g_hash_table_lookup (display->window_ids, &xwindow);
}
void
2001-05-31 02:42:58 -04:00
meta_display_register_x_window (MetaDisplay *display,
Window *xwindowp,
MetaWindow *window)
2001-05-30 11:36:31 -04:00
{
2001-05-31 02:42:58 -04:00
g_return_if_fail (g_hash_table_lookup (display->window_ids, xwindowp) == NULL);
2001-05-30 11:36:31 -04:00
2001-05-31 02:42:58 -04:00
g_hash_table_insert (display->window_ids, xwindowp, window);
}
void
meta_display_unregister_x_window (MetaDisplay *display,
Window xwindow)
{
g_return_if_fail (g_hash_table_lookup (display->window_ids, &xwindow) != NULL);
g_hash_table_remove (display->window_ids, &xwindow);
2001-05-30 11:36:31 -04:00
}