* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Metacity X display handler */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2002, 2003, 2004 Red Hat, Inc.
* Copyright (C) 2003, 2004 Rob Adams
* Copyright (C) 2004-2006 Elijah Newren
*
* 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.
*/
/**
* \file display.c
*
* \brief Handles operations on an X display.
*
* The display is represented as a MetaDisplay struct.
*
* \bug Originally we had the idea that there could be multiple MetaDisplay
* structs in one Metacity process, but as the code currently stands, only
* one can be initialised; it is a singleton class. We should go through and
* remove all the code that iterates over the lists of displays later.
* See <http://bugzilla.gnome.org/show_bug.cgi?id=499301>.
*/
#include <config.h>
#include "display.h"
#include "util.h"
#include "main.h"
#include "screen.h"
#include "window.h"
#include "window-props.h"
#include "group-props.h"
#include "frame.h"
#include "errors.h"
#include "keybindings.h"
#include "prefs.h"
#include "resizepopup.h"
#include "xprops.h"
#include "workspace.h"
#include "bell.h"
#include "effects.h"
#include "compositor.h"
#include <X11/Xatom.h>
#include <X11/cursorfont.h>
#ifdef HAVE_SOLARIS_XINERAMA
#include <X11/extensions/xinerama.h>
#endif
#ifdef HAVE_XFREE_XINERAMA
#include <X11/extensions/Xinerama.h>
#endif
#ifdef HAVE_RANDR
#include <X11/extensions/Xrandr.h>
#endif
#ifdef HAVE_SHAPE
#include <X11/extensions/shape.h>
#endif
#ifdef HAVE_RENDER
#include <X11/extensions/Xrender.h>
#endif
#ifdef HAVE_XKB
#include <X11/XKBlib.h>
#endif
#ifdef HAVE_XCURSOR
#include <X11/Xcursor/Xcursor.h>
#endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
#include <X11/extensions/Xcomposite.h>
#include <X11/extensions/Xdamage.h>
#include <X11/extensions/Xfixes.h>
#endif
#include <string.h>
#define GRAB_OP_IS_WINDOW_SWITCH(g) \
(g == META_GRAB_OP_KEYBOARD_TABBING_NORMAL || \
g == META_GRAB_OP_KEYBOARD_TABBING_DOCK || \
g == META_GRAB_OP_KEYBOARD_TABBING_GROUP || \
g == META_GRAB_OP_KEYBOARD_ESCAPING_NORMAL || \
g == META_GRAB_OP_KEYBOARD_ESCAPING_DOCK || \
g == META_GRAB_OP_KEYBOARD_ESCAPING_GROUP)
/**
* \defgroup pings Pings
*
* Sometimes we want to see whether a window is responding,
* so we send it a "ping" message and see whether it sends us back a "pong"
* message within a reasonable time. Here we have a system which lets us
* nominate one function to be called if we get the pong in time and another
* function if we don't. The system is rather more complicated than it needs
* to be, since we only ever use it to destroy windows which are asked to
* close themselves and don't do so within a reasonable amount of time, and
* therefore we always use the same callbacks. It's possible that we might
* use it for other things in future, or on the other hand we might decide
* that we're never going to do so and simplify it a bit.
*/
/**
* Describes a ping on a window. When we send a ping to a window, we build
* one of these structs, and it eventually gets passed to the timeout function
* or to the function which handles the response from the window. If the window
* does or doesn't respond to the ping, we use this information to deal with
* these facts; we have a handler function for each.
*
* \ingroup pings
*/
typedef struct
{
MetaDisplay *display;
Window xwindow;
guint32 timestamp;
MetaWindowPingFunc ping_reply_func;
MetaWindowPingFunc ping_timeout_func;
void *user_data;
guint ping_timeout_id;
} MetaPingData;
typedef struct
{
MetaDisplay *display;
Window xwindow;
} MetaAutoRaiseData;
static GSList *all_displays = NULL;
static void meta_spew_event (MetaDisplay *display,
XEvent *event);
static gboolean event_callback (XEvent *event,
gpointer data);
static Window event_get_modified_window (MetaDisplay *display,
XEvent *event);
static guint32 event_get_time (MetaDisplay *display,
XEvent *event);
static void process_request_frame_extents (MetaDisplay *display,
XEvent *event);
static void process_pong_message (MetaDisplay *display,
XEvent *event);
static void process_selection_request (MetaDisplay *display,
XEvent *event);
static void process_selection_clear (MetaDisplay *display,
XEvent *event);
static void update_window_grab_modifiers (MetaDisplay *display);
static void prefs_changed_callback (MetaPreference pref,
void *data);
static void sanity_check_timestamps (MetaDisplay *display,
guint32 known_good_timestamp);
MetaGroup* get_focussed_group (MetaDisplay *display);
/**
* Destructor for MetaPingData structs. Will destroy the
* event source for the struct as well.
*
* \ingroup pings
*/
static void
ping_data_free (MetaPingData *ping_data)
{
/* Remove the timeout */
if (ping_data->ping_timeout_id != 0)
g_source_remove (ping_data->ping_timeout_id);
g_free (ping_data);
}
/**
* Frees every pending ping structure for the given X window on the
* given display. This means that we also destroy the timeouts.
*
* \param display The display the window appears on
* \param xwindow The X ID of the window whose pings we should remove
*
* \ingroup pings
*
*/
static void
remove_pending_pings_for_window (MetaDisplay *display, Window xwindow)
{
GSList *tmp;
GSList *dead;
/* could obviously be more efficient, don't care */
/* build list to be removed */
dead = NULL;
for (tmp = display->pending_pings; tmp; tmp = tmp->next)
{
MetaPingData *ping_data = tmp->data;
if (ping_data->xwindow == xwindow)
dead = g_slist_prepend (dead, ping_data);
}
/* remove what we found */
for (tmp = dead; tmp; tmp = tmp->next)
{
MetaPingData *ping_data = tmp->data;
display->pending_pings = g_slist_remove (display->pending_pings, ping_data);
ping_data_free (ping_data);
}
g_slist_free (dead);
}
#ifdef HAVE_STARTUP_NOTIFICATION
static void
sn_error_trap_push (SnDisplay *sn_display,
Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display != NULL)
meta_error_trap_push (display);
}
static void
sn_error_trap_pop (SnDisplay *sn_display,
Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display != NULL)
meta_error_trap_pop (display, FALSE);
}
#endif
static void
enable_compositor (MetaDisplay *display,
gboolean composite_windows)
{
GSList *list;
if (!META_DISPLAY_HAS_COMPOSITE (display) ||
!META_DISPLAY_HAS_DAMAGE (display) ||
!META_DISPLAY_HAS_XFIXES (display) ||
!META_DISPLAY_HAS_RENDER (display))
{
meta_warning (_("Missing %s extension required for compositing"),
!META_DISPLAY_HAS_COMPOSITE (display) ? "composite" :
!META_DISPLAY_HAS_DAMAGE (display) ? "damage" :
!META_DISPLAY_HAS_XFIXES (display) ? "xfixes" : "render");
return;
}
if (!display->compositor)
display->compositor = meta_compositor_new (display);
if (!display->compositor)
return;
for (list = display->screens; list != NULL; list = list->next)
{
MetaScreen *screen = list->data;
meta_compositor_manage_screen (screen->display->compositor,
screen);
if (composite_windows)
meta_screen_composite_all_windows (screen);
}
}
static void
disable_compositor (MetaDisplay *display)
{
GSList *list;
if (!display->compositor)
return;
for (list = display->screens; list != NULL; list = list->next)
{
MetaScreen *screen = list->data;
meta_compositor_unmanage_screen (screen->display->compositor,
screen);
}
meta_compositor_destroy (display->compositor);
display->compositor = NULL;
}
/**
* Opens a new display, sets it up, initialises all the X extensions
* we will need, and adds it to the list of displays.
*
* \return True if the display was opened successfully, and False
* otherwise-- that is, if the display doesn't exist or it already
* has a window manager.
*
* \bug The list of atom_names is prone to get out of sync with the
* main list; I'd rather include them in that list using the stringify
* operator or something.
*
* \bug MetaDisplay is (currently) a singleton, but the code pretends
* it isn't; at some point we will decide whether to acknowledge this
* and simplify.
*
* \ingroup main
*/
gboolean
meta_display_open (void)
{
MetaDisplay *display;
Display *xdisplay;
GSList *screens;
GSList *tmp;
int i;
guint32 timestamp;
/* Remember to edit code that assigns each atom to display struct
* when adding an atom name here.
*/
char *atom_names[] = {
"_NET_WM_NAME",
"WM_PROTOCOLS",
"WM_TAKE_FOCUS",
"WM_DELETE_WINDOW",
"WM_STATE",
"_NET_CLOSE_WINDOW",
"_NET_WM_STATE",
"_MOTIF_WM_HINTS",
"_NET_WM_STATE_SHADED",
"_NET_WM_STATE_MAXIMIZED_HORZ",
"_NET_WM_STATE_MAXIMIZED_VERT",
"_NET_WM_DESKTOP",
"_NET_NUMBER_OF_DESKTOPS",
"WM_CHANGE_STATE",
"SM_CLIENT_ID",
"WM_CLIENT_LEADER",
"WM_WINDOW_ROLE",
"_NET_CURRENT_DESKTOP",
"_NET_SUPPORTING_WM_CHECK",
"_NET_SUPPORTED",
"_NET_WM_WINDOW_TYPE",
"_NET_WM_WINDOW_TYPE_DESKTOP",
"_NET_WM_WINDOW_TYPE_DOCK",
"_NET_WM_WINDOW_TYPE_TOOLBAR",
"_NET_WM_WINDOW_TYPE_MENU",
"_NET_WM_WINDOW_TYPE_DIALOG",
"_NET_WM_WINDOW_TYPE_NORMAL",
"_NET_WM_STATE_MODAL",
"_NET_CLIENT_LIST",
"_NET_CLIENT_LIST_STACKING",
"_NET_WM_STATE_SKIP_TASKBAR",
"_NET_WM_STATE_SKIP_PAGER",
"_NET_WM_ICON_NAME",
"_NET_WM_ICON",
"_NET_WM_ICON_GEOMETRY",
"UTF8_STRING",
"WM_ICON_SIZE",
"_KWM_WIN_ICON",
"_NET_WM_MOVERESIZE",
"_NET_ACTIVE_WINDOW",
"_METACITY_RESTART_MESSAGE",
"_NET_WM_STRUT",
"_METACITY_RELOAD_THEME_MESSAGE",
"_METACITY_SET_KEYBINDINGS_MESSAGE",
"_NET_WM_STATE_HIDDEN",
"_NET_WM_WINDOW_TYPE_UTILITY",
"_NET_WM_WINDOW_TYPE_SPLASH",
"_NET_WM_STATE_FULLSCREEN",
"_NET_WM_PING",
"_NET_WM_PID",
"WM_CLIENT_MACHINE",
"_NET_WORKAREA",
"_NET_SHOWING_DESKTOP",
"_NET_DESKTOP_LAYOUT",
"MANAGER",
"TARGETS",
"MULTIPLE",
"TIMESTAMP",
"VERSION",
"ATOM_PAIR",
"_NET_DESKTOP_NAMES",
"_NET_WM_ALLOWED_ACTIONS",
"_NET_WM_ACTION_MOVE",
"_NET_WM_ACTION_RESIZE",
"_NET_WM_ACTION_SHADE",
"_NET_WM_ACTION_STICK",
"_NET_WM_ACTION_MAXIMIZE_HORZ",
"_NET_WM_ACTION_MAXIMIZE_VERT",
"_NET_WM_ACTION_CHANGE_DESKTOP",
"_NET_WM_ACTION_CLOSE",
"_NET_WM_STATE_ABOVE",
"_NET_WM_STATE_BELOW",
"_NET_STARTUP_ID",
"_METACITY_TOGGLE_VERBOSE",
"_NET_WM_SYNC_REQUEST",
"_NET_WM_SYNC_REQUEST_COUNTER",
"_GNOME_PANEL_ACTION",
"_GNOME_PANEL_ACTION_MAIN_MENU",
"_GNOME_PANEL_ACTION_RUN_DIALOG",
"_METACITY_SENTINEL",
"_NET_WM_STRUT_PARTIAL",
"_NET_WM_ACTION_FULLSCREEN",
"_NET_WM_ACTION_MINIMIZE",
"_NET_FRAME_EXTENTS",
"_NET_REQUEST_FRAME_EXTENTS",
"_NET_WM_USER_TIME",
"_NET_WM_STATE_DEMANDS_ATTENTION",
"_NET_RESTACK_WINDOW",
"_NET_MOVERESIZE_WINDOW",
"_NET_DESKTOP_GEOMETRY",
"_NET_DESKTOP_VIEWPORT",
"_METACITY_VERSION",
"_NET_WM_VISIBLE_NAME",
"_NET_WM_VISIBLE_ICON_NAME",
"_NET_WM_USER_TIME_WINDOW",
"_NET_WM_ACTION_ABOVE",
"_NET_WM_ACTION_BELOW",
};
Atom atoms[G_N_ELEMENTS(atom_names)];
meta_verbose ("Opening display '%s'\n", XDisplayName (NULL));
xdisplay = meta_ui_get_display ();
if (xdisplay == NULL)
{
meta_warning (_("Failed to open X Window System display '%s'\n"),
XDisplayName (NULL));
return FALSE;
}
if (meta_is_syncing ())
XSynchronize (xdisplay, True);
display = g_new (MetaDisplay, 1);
display->closing = 0;
/* here we use XDisplayName which is what the user
* probably put in, vs. DisplayString(display) which is
* canonicalized by XOpenDisplay()
*/
display->name = g_strdup (XDisplayName (NULL));
display->xdisplay = xdisplay;
display->error_trap_synced_at_last_pop = TRUE;
display->error_traps = 0;
display->error_trap_handler = NULL;
display->server_grab_count = 0;
display->display_opening = TRUE;
display->pending_pings = NULL;
display->autoraise_timeout_id = 0;
display->autoraise_window = NULL;
display->focus_window = NULL;
display->expected_focus_window = NULL;
display->grab_old_window_stacking = NULL;
display->mouse_mode = TRUE; /* Only relevant for mouse or sloppy focus */
display->allow_terminal_deactivation = TRUE; /* Only relevant for when a
terminal has the focus */
#ifdef HAVE_XSYNC
display->grab_sync_request_alarm = None;
#endif
/* FIXME copy the checks from GDK probably */
display->static_gravity_works = g_getenv ("METACITY_USE_STATIC_GRAVITY") != NULL;
/* we have to go ahead and do this so error handlers work */
all_displays = g_slist_prepend (all_displays, display);
meta_bell_init (display);
meta_display_init_keys (display);
update_window_grab_modifiers (display);
meta_prefs_add_listener (prefs_changed_callback, display);
meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
XInternAtoms (display->xdisplay, atom_names, G_N_ELEMENTS (atom_names),
False, atoms);
display->atom_net_wm_name = atoms[0];
display->atom_wm_protocols = atoms[1];
display->atom_wm_take_focus = atoms[2];
display->atom_wm_delete_window = atoms[3];
display->atom_wm_state = atoms[4];
display->atom_net_close_window = atoms[5];
display->atom_net_wm_state = atoms[6];
display->atom_motif_wm_hints = atoms[7];
display->atom_net_wm_state_shaded = atoms[8];
display->atom_net_wm_state_maximized_horz = atoms[9];
display->atom_net_wm_state_maximized_vert = atoms[10];
display->atom_net_wm_desktop = atoms[11];
display->atom_net_number_of_desktops = atoms[12];
display->atom_wm_change_state = atoms[13];
display->atom_sm_client_id = atoms[14];
display->atom_wm_client_leader = atoms[15];
display->atom_wm_window_role = atoms[16];
display->atom_net_current_desktop = atoms[17];
display->atom_net_supporting_wm_check = atoms[18];
display->atom_net_supported = atoms[19];
display->atom_net_wm_window_type = atoms[20];
display->atom_net_wm_window_type_desktop = atoms[21];
display->atom_net_wm_window_type_dock = atoms[22];
display->atom_net_wm_window_type_toolbar = atoms[23];
display->atom_net_wm_window_type_menu = atoms[24];
display->atom_net_wm_window_type_dialog = atoms[25];
display->atom_net_wm_window_type_normal = atoms[26];
display->atom_net_wm_state_modal = atoms[27];
display->atom_net_client_list = atoms[28];
display->atom_net_client_list_stacking = atoms[29];
display->atom_net_wm_state_skip_taskbar = atoms[30];
display->atom_net_wm_state_skip_pager = atoms[31];
display->atom_net_wm_icon_name = atoms[32];
display->atom_net_wm_icon = atoms[33];
display->atom_net_wm_icon_geometry = atoms[34];
display->atom_utf8_string = atoms[35];
display->atom_wm_icon_size = atoms[36];
display->atom_kwm_win_icon = atoms[37];
display->atom_net_wm_moveresize = atoms[38];
display->atom_net_active_window = atoms[39];
display->atom_metacity_restart_message = atoms[40];
display->atom_net_wm_strut = atoms[41];
display->atom_metacity_reload_theme_message = atoms[42];
display->atom_metacity_set_keybindings_message = atoms[43];
display->atom_net_wm_state_hidden = atoms[44];
display->atom_net_wm_window_type_utility = atoms[45];
display->atom_net_wm_window_type_splash = atoms[46];
display->atom_net_wm_state_fullscreen = atoms[47];
display->atom_net_wm_ping = atoms[48];
display->atom_net_wm_pid = atoms[49];
display->atom_wm_client_machine = atoms[50];
display->atom_net_workarea = atoms[51];
display->atom_net_showing_desktop = atoms[52];
display->atom_net_desktop_layout = atoms[53];
display->atom_manager = atoms[54];
display->atom_targets = atoms[55];
display->atom_multiple = atoms[56];
display->atom_timestamp = atoms[57];
display->atom_version = atoms[58];
display->atom_atom_pair = atoms[59];
display->atom_net_desktop_names = atoms[60];
display->atom_net_wm_allowed_actions = atoms[61];
display->atom_net_wm_action_move = atoms[62];
display->atom_net_wm_action_resize = atoms[63];
display->atom_net_wm_action_shade = atoms[64];
display->atom_net_wm_action_stick = atoms[65];
display->atom_net_wm_action_maximize_horz = atoms[66];
display->atom_net_wm_action_maximize_vert = atoms[67];
display->atom_net_wm_action_change_desktop = atoms[68];
display->atom_net_wm_action_close = atoms[69];
display->atom_net_wm_state_above = atoms[70];
display->atom_net_wm_state_below = atoms[71];
display->atom_net_startup_id = atoms[72];
display->atom_metacity_toggle_verbose = atoms[73];
display->atom_net_wm_sync_request = atoms[74];
display->atom_net_wm_sync_request_counter = atoms[75];
display->atom_gnome_panel_action = atoms[76];
display->atom_gnome_panel_action_main_menu = atoms[77];
display->atom_gnome_panel_action_run_dialog = atoms[78];
display->atom_metacity_sentinel = atoms[79];
display->atom_net_wm_strut_partial = atoms[80];
display->atom_net_wm_action_fullscreen = atoms[81];
display->atom_net_wm_action_minimize = atoms[82];
display->atom_net_frame_extents = atoms[83];
display->atom_net_request_frame_extents = atoms[84];
display->atom_net_wm_user_time = atoms[85];
display->atom_net_wm_state_demands_attention = atoms[86];
display->atom_net_restack_window = atoms[87];
display->atom_net_moveresize_window = atoms[88];
display->atom_net_desktop_geometry = atoms[89];
display->atom_net_desktop_viewport = atoms[90];
display->atom_metacity_version = atoms[91];
display->atom_net_wm_visible_name = atoms[92];
display->atom_net_wm_visible_icon_name = atoms[93];
display->atom_net_wm_user_time_window = atoms[94];
display->atom_net_wm_action_above = atoms[95];
display->atom_net_wm_action_below = atoms[96];
display->prop_hooks = NULL;
meta_display_init_window_prop_hooks (display);
display->group_prop_hooks = NULL;
meta_display_init_group_prop_hooks (display);
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
* created in screen_new
*/
display->leader_window = None;
display->timestamp_pinging_window = None;
display->xinerama_cache_invalidated = TRUE;
display->groups_by_leader = NULL;
display->window_with_menu = NULL;
display->window_menu = NULL;
display->screens = NULL;
display->active_screen = NULL;
#ifdef HAVE_STARTUP_NOTIFICATION
display->sn_display = sn_display_new (display->xdisplay,
sn_error_trap_push,
sn_error_trap_pop);
#endif
display->events = NULL;
/* Get events */
meta_ui_add_event_func (display->xdisplay,
event_callback,
display);
display->window_ids = g_hash_table_new (meta_unsigned_long_hash,
meta_unsigned_long_equal);
i = 0;
while (i < N_IGNORED_SERIALS)
{
display->ignored_serials[i] = 0;
++i;
}
display->ungrab_should_not_cause_focus_window = None;
display->current_time = CurrentTime;
display->sentinel_counter = 0;
display->grab_resize_timeout_id = 0;
display->grab_have_keyboard = FALSE;
#ifdef HAVE_XKB
display->last_bell_time = 0;
#endif
display->grab_op = META_GRAB_OP_NONE;
display->grab_wireframe_active = FALSE;
display->grab_window = NULL;
display->grab_screen = NULL;
display->grab_resize_popup = NULL;
display->grab_edge_resistance_data = NULL;
#ifdef HAVE_XSYNC
{
int major, minor;
display->have_xsync = FALSE;
display->xsync_error_base = 0;
display->xsync_event_base = 0;
/* I don't think we really have to fill these in */
major = SYNC_MAJOR_VERSION;
minor = SYNC_MINOR_VERSION;
if (!XSyncQueryExtension (display->xdisplay,
&display->xsync_event_base,
&display->xsync_error_base) ||
!XSyncInitialize (display->xdisplay,
&major, &minor))
{
display->xsync_error_base = 0;
display->xsync_event_base = 0;
}
else
display->have_xsync = TRUE;
meta_verbose ("Attempted to init Xsync, found version %d.%d error base %d event base %d\n",
major, minor,
display->xsync_error_base,
display->xsync_event_base);
}
#else /* HAVE_XSYNC */
meta_verbose ("Not compiled with Xsync support\n");
#endif /* !HAVE_XSYNC */
#ifdef HAVE_SHAPE
{
display->have_shape = FALSE;
display->shape_error_base = 0;
display->shape_event_base = 0;
if (!XShapeQueryExtension (display->xdisplay,
&display->shape_event_base,
&display->shape_error_base))
{
display->shape_error_base = 0;
display->shape_event_base = 0;
}
else
display->have_shape = TRUE;
meta_verbose ("Attempted to init Shape, found error base %d event base %d\n",
display->shape_error_base,
display->shape_event_base);
}
#else /* HAVE_SHAPE */
meta_verbose ("Not compiled with Shape support\n");
#endif /* !HAVE_SHAPE */
#ifdef HAVE_RENDER
{
display->have_render = FALSE;
display->render_error_base = 0;
display->render_event_base = 0;
if (!XRenderQueryExtension (display->xdisplay,
&display->render_event_base,
&display->render_error_base))
{
display->render_error_base = 0;
display->render_event_base = 0;
}
else
display->have_render = TRUE;
meta_verbose ("Attempted to init Render, found error base %d event base %d\n",
display->render_error_base,
display->render_event_base);
}
#else /* HAVE_RENDER */
meta_verbose ("Not compiled with Render support\n");
#endif /* !HAVE_RENDER */
#ifdef HAVE_COMPOSITE_EXTENSIONS
{
display->have_composite = FALSE;
display->composite_error_base = 0;
display->composite_event_base = 0;
if (!XCompositeQueryExtension (display->xdisplay,
&display->composite_event_base,
&display->composite_error_base))
{
display->composite_error_base = 0;
display->composite_event_base = 0;
}
else
display->have_composite = TRUE;
meta_verbose ("Attempted to init Composite, found error base %d event base %d\n",
display->composite_error_base,
display->composite_event_base);
display->have_damage = FALSE;
display->damage_error_base = 0;
display->damage_event_base = 0;
if (!XDamageQueryExtension (display->xdisplay,
&display->damage_event_base,
&display->damage_error_base))
{
display->damage_error_base = 0;
display->damage_event_base = 0;
}
else
display->have_damage = TRUE;
meta_verbose ("Attempted to init Damage, found error base %d event base %d\n",
display->damage_error_base,
display->damage_event_base);
display->have_xfixes = FALSE;
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
if (!XFixesQueryExtension (display->xdisplay,
&display->xfixes_event_base,
&display->xfixes_error_base))
{
display->xfixes_error_base = 0;
display->xfixes_event_base = 0;
}
else
display->have_xfixes = TRUE;
meta_verbose ("Attempted to init XFixes, found error base %d event base %d\n",
display->xfixes_error_base,
display->xfixes_event_base);
}
#else /* HAVE_COMPOSITE_EXTENSIONS */
meta_verbose ("Not compiled with Composite support\n");
#endif /* !HAVE_COMPOSITE_EXTENSIONS */
#ifdef HAVE_XCURSOR
{
XcursorSetTheme (display->xdisplay, meta_prefs_get_cursor_theme ());
XcursorSetDefaultSize (display->xdisplay, meta_prefs_get_cursor_size
|