Пример #1
0
static Window
get_output_window (MetaScreen *screen)
{
    MetaDisplay *display = meta_screen_get_display (screen);
    Display     *xdisplay = meta_display_get_xdisplay (display);
    Window       output, xroot;
    XWindowAttributes attr;
    long         event_mask;

    xroot = meta_screen_get_xroot (screen);

    event_mask = FocusChangeMask |
                 ExposureMask |
                 EnterWindowMask | LeaveWindowMask |
                 PointerMotionMask |
                 PropertyChangeMask |
                 ButtonPressMask | ButtonReleaseMask |
                 KeyPressMask | KeyReleaseMask;

    output = XCompositeGetOverlayWindow (xdisplay, xroot);

    if (XGetWindowAttributes (xdisplay, output, &attr))
    {
        event_mask |= attr.your_event_mask;
    }

    XSelectInput (xdisplay, output, event_mask);

    return output;
}
static void
detach_pixmap (MetaSurfaceActorX11 *self)
{
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = priv->display;
  Display *xdisplay = meta_display_get_xdisplay (display);
  MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self));

  if (priv->pixmap == None)
    return;

  /* Get rid of all references to the pixmap before freeing it; it's unclear whether
   * you are supposed to be able to free a GLXPixmap after freeing the underlying
   * pixmap, but it certainly doesn't work with current DRI/Mesa
   */
  meta_shaped_texture_set_texture (stex, NULL);
  cogl_flush ();

  meta_error_trap_push (display);
  XFreePixmap (xdisplay, priv->pixmap);
  priv->pixmap = None;
  meta_error_trap_pop (display);

  cogl_object_unref (priv->texture);
  priv->texture = NULL;
}
Пример #3
0
void
meta_compositor_sync_screen_size (MetaCompositor  *compositor,
                                  MetaScreen	  *screen,
                                  guint		   width,
                                  guint		   height)
{
    MetaDisplay    *display = meta_screen_get_display (screen);
    MetaCompScreen *info    = meta_screen_get_compositor_data (screen);
    Display        *xdisplay;
    Window          xwin;

    DEBUG_TRACE ("meta_compositor_sync_screen_size\n");
    g_return_if_fail (info);

    xdisplay = meta_display_get_xdisplay (display);
    xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));

    XResizeWindow (xdisplay, xwin, width, height);

    meta_background_actor_screen_size_changed (screen);

    meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
                  meta_screen_get_screen_number (screen),
                  width, height);
}
Пример #4
0
void
meta_set_stage_input_region (MetaScreen   *screen,
                             XserverRegion region)
{
    MetaCompScreen *info = meta_screen_get_compositor_data (screen);
    MetaDisplay  *display = meta_screen_get_display (screen);
    Display      *xdpy    = meta_display_get_xdisplay (display);

    if (info->stage && info->output)
    {
        do_set_stage_input_region (screen, region);
    }
    else
    {
        /* Reset info->pending_input_region if one existed before and set the new
         * one to use it later. */
        if (info->pending_input_region)
        {
            XFixesDestroyRegion (xdpy, info->pending_input_region);
            info->pending_input_region = None;
        }
        if (region != None)
        {
            info->pending_input_region = XFixesCreateRegion (xdpy, NULL, 0);
            XFixesCopyRegion (xdpy, info->pending_input_region, region);
        }
    }
}
Пример #5
0
void
meta_set_stage_input_region (MetaScreen   *screen,
                             XserverRegion region)
{
  /* As a wayland compositor we can simply ignore all this trickery
   * for setting an input region on the stage for capturing events in
   * clutter since all input comes to us first and we get to choose
   * who else sees them.
   */
  if (!meta_is_wayland_compositor ())
    {
      MetaDisplay *display = screen->display;
      MetaCompositor *compositor = display->compositor;
      Display *xdpy = meta_display_get_xdisplay (display);
      Window xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));

      XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);

      /* It's generally a good heuristic that when a crossing event is generated because
       * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
       * it's not the user doing something, it's the environment changing under the user.
       */
      meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
      XFixesSetWindowShapeRegion (xdpy, compositor->output, ShapeInput, 0, 0, region);
    }
}
Пример #6
0
/**
 * shell_global_grab_keyboard:
 * @global: a #ShellGlobal
 *
 * Grab the keyboard to the stage window. The stage will receive
 * all keyboard events until shell_global_ungrab_keyboard() is called.
 * This is appropriate to do when the desktop goes into a special
 * mode where no normal global key shortcuts or application keyboard
 * processing should happen.
 */
gboolean
shell_global_grab_keyboard (ShellGlobal *global)
{
  MetaScreen *screen = mutter_plugin_get_screen (global->plugin);
  MetaDisplay *display = meta_screen_get_display (screen);
  Display *xdisplay = meta_display_get_xdisplay (display);
  ClutterStage *stage = CLUTTER_STAGE (mutter_plugin_get_stage (global->plugin));
  Window stagewin = clutter_x11_get_stage_window (stage);

  /* FIXME: we need to coordinate with the rest of Metacity or we
   * may grab the keyboard away from other portions of Metacity
   * and leave Metacity in a confused state. An X client is allowed
   * to overgrab itself, though not allowed to grab they keyboard
   * away from another applications.
   */
  if (global->keyboard_grabbed)
    return FALSE;

  if (XGrabKeyboard (xdisplay, stagewin,
                     False, /* owner_events - steal events from the rest of metacity */
                     GrabModeAsync, GrabModeAsync,
                     CurrentTime) != Success)
    return FALSE; /* probably AlreadyGrabbed, some other app has a keyboard grab */

  global->keyboard_grabbed = TRUE;

  return TRUE;
}
static void
create_damage (MetaSurfaceActorX11 *self)
{
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  Display *xdisplay = meta_display_get_xdisplay (priv->display);
  Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);

  priv->damage = XDamageCreate (xdisplay, xwindow, XDamageReportBoundingBox);
}
Пример #8
0
void
meta_compositor_unmanage_screen (MetaCompositor *compositor,
                                 MetaScreen     *screen)
{
    MetaDisplay    *display       = meta_screen_get_display (screen);
    Display        *xdisplay      = meta_display_get_xdisplay (display);
    Window          xroot         = meta_screen_get_xroot (screen);

    /* This is the most important part of cleanup - we have to do this
     * before giving up the window manager selection or the next
     * window manager won't be able to redirect subwindows */
    XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
}
static void
free_damage (MetaSurfaceActorX11 *self)
{
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = priv->display;
  Display *xdisplay = meta_display_get_xdisplay (display);

  if (priv->damage == None)
    return;

  meta_error_trap_push (display);
  XDamageDestroy (xdisplay, priv->damage);
  priv->damage = None;
  meta_error_trap_pop (display);
}
Пример #10
0
void
meta_compositor_unmanage (MetaCompositor *compositor)
{
  if (!meta_is_wayland_compositor ())
    {
      MetaDisplay *display = compositor->display;
      Display *xdisplay = meta_display_get_xdisplay (display);
      Window xroot = display->screen->xroot;

      /* This is the most important part of cleanup - we have to do this
       * before giving up the window manager selection or the next
       * window manager won't be able to redirect subwindows */
      XCompositeUnredirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
    }
}
Пример #11
0
void
meta_empty_stage_input_region (MetaScreen *screen)
{
  /* Using a static region here is a bit hacky, but Metacity never opens more than
   * one XDisplay, so it works fine. */
  static XserverRegion region = None;

  if (region == None)
    {
      MetaDisplay  *display = meta_screen_get_display (screen);
      Display      *xdpy    = meta_display_get_xdisplay (display);
      region = XFixesCreateRegion (xdpy, NULL, 0);
    }

  meta_set_stage_input_region (screen, region);
}
Пример #12
0
/**
 * shell_global_ungrab_keyboard:
 * @global: a #ShellGlobal
 *
 * Undoes the effect of shell_global_grab_keyboard
 */
void
shell_global_ungrab_keyboard (ShellGlobal *global)
{
  MetaScreen *screen;
  MetaDisplay *display;
  Display *xdisplay;

  g_return_if_fail (global->keyboard_grabbed);

  screen = mutter_plugin_get_screen (global->plugin);
  display = meta_screen_get_display (screen);
  xdisplay = meta_display_get_xdisplay (display);

  XUngrabKeyboard (xdisplay, CurrentTime);

  global->keyboard_grabbed = FALSE;
}
Пример #13
0
static void
do_set_stage_input_region (MetaScreen   *screen,
                           XserverRegion region)
{
    MetaCompScreen *info = meta_screen_get_compositor_data (screen);
    MetaDisplay *display = meta_screen_get_display (screen);
    Display        *xdpy = meta_display_get_xdisplay (display);
    Window        xstage = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));

    XFixesSetWindowShapeRegion (xdpy, xstage, ShapeInput, 0, 0, region);

    /* It's generally a good heuristic that when a crossing event is generated because
     * we reshape the overlay, we don't want it to affect focus-follows-mouse focus -
     * it's not the user doing something, it's the environment changing under the user.
     */
    meta_display_add_ignored_crossing_serial (display, XNextRequest (xdpy));
    XFixesSetWindowShapeRegion (xdpy, info->output, ShapeInput, 0, 0, region);
}
static void
update_pixmap (MetaSurfaceActorX11 *self)
{
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = priv->display;
  Display *xdisplay = meta_display_get_xdisplay (display);

  if (priv->size_changed)
    {
      detach_pixmap (self);
      priv->size_changed = FALSE;
    }

  if (priv->pixmap == None)
    {
      Pixmap new_pixmap;
      Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);

      meta_error_trap_push (display);
      new_pixmap = XCompositeNameWindowPixmap (xdisplay, xwindow);

      if (meta_error_trap_pop_with_return (display) != Success)
        {
          /* Probably a BadMatch if the window isn't viewable; we could
           * GrabServer/GetWindowAttributes/NameWindowPixmap/UngrabServer/Sync
           * to avoid this, but there's no reason to take two round trips
           * when one will do. (We need that Sync if we want to handle failures
           * for any reason other than !viewable. That's unlikely, but maybe
           * we'll BadAlloc or something.)
           */
          new_pixmap = None;
        }

      if (new_pixmap == None)
        {
          meta_verbose ("Unable to get named pixmap for %s\n",
                        meta_window_get_description (priv->window));
          return;
        }

      set_pixmap (self, new_pixmap);
    }
}
static void
meta_surface_actor_x11_pre_paint (MetaSurfaceActor *actor)
{
  MetaSurfaceActorX11 *self = META_SURFACE_ACTOR_X11 (actor);
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = priv->display;
  Display *xdisplay = meta_display_get_xdisplay (display);

  if (priv->received_damage)
    {
      meta_error_trap_push (display);
      XDamageSubtract (xdisplay, priv->damage, None, None);
      meta_error_trap_pop (display);

      priv->received_damage = FALSE;
    }

  update_pixmap (self);
}
Пример #16
0
static void
redirect_windows (MetaScreen *screen)
{
  MetaDisplay *display       = meta_screen_get_display (screen);
  Display     *xdisplay      = meta_display_get_xdisplay (display);
  Window       xroot         = meta_screen_get_xroot (screen);
  int          screen_number = meta_screen_get_screen_number (screen);
  guint        n_retries;
  guint        max_retries;

  if (meta_get_replace_current_wm ())
    max_retries = 5;
  else
    max_retries = 1;

  n_retries = 0;

  /* Some compositors (like old versions of Mutter) might not properly unredirect
   * subwindows before destroying the WM selection window; so we wait a while
   * for such a compositor to exit before giving up.
   */
  while (TRUE)
    {
      meta_error_trap_push (display);
      XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
      XSync (xdisplay, FALSE);

      if (!meta_error_trap_pop_with_return (display))
        break;

      if (n_retries == max_retries)
        {
          /* This probably means that a non-WM compositor like xcompmgr is running;
           * we have no way to get it to exit */
          meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."),
                      screen_number, display->name);
        }

      n_retries++;
      g_usleep (G_USEC_PER_SEC);
    }
}
Пример #17
0
/**
 * meta_compositor_new: (skip)
 *
 */
MetaCompositor *
meta_compositor_new (MetaDisplay *display)
{
    char *atom_names[] = {
        "_XROOTPMAP_ID",
        "_XSETROOT_ID",
        "_NET_WM_WINDOW_OPACITY",
    };
    Atom                   atoms[G_N_ELEMENTS(atom_names)];
    MetaCompositor        *compositor;
    Display               *xdisplay = meta_display_get_xdisplay (display);

    if (!composite_at_least_version (display, 0, 3))
        return NULL;

    compositor = g_new0 (MetaCompositor, 1);

    compositor->display = display;

    if (g_getenv("META_DISABLE_MIPMAPS"))
        compositor->no_mipmaps = TRUE;

    meta_verbose ("Creating %d atoms\n", (int) G_N_ELEMENTS (atom_names));
    XInternAtoms (xdisplay, atom_names, G_N_ELEMENTS (atom_names),
                  False, atoms);

    g_signal_connect (meta_shadow_factory_get_default (),
                      "changed",
                      G_CALLBACK (on_shadow_factory_changed),
                      compositor);

    compositor->atom_x_root_pixmap = atoms[0];
    compositor->atom_x_set_root = atoms[1];
    compositor->atom_net_wm_window_opacity = atoms[2];

    compositor->repaint_func_id = clutter_threads_add_repaint_func (meta_repaint_func,
                                  compositor,
                                  NULL);

    return compositor;
}
Пример #18
0
LOCAL_SYMBOL void
meta_end_modal_for_plugin (MetaScreen     *screen,
                           MetaPlugin     *plugin,
                           guint32         timestamp)
{
    MetaDisplay    *display    = meta_screen_get_display (screen);
    Display        *xdpy = meta_display_get_xdisplay (display);
    MetaCompositor *compositor = display->compositor;

    g_return_if_fail (compositor->modal_plugin == plugin);

    XUngrabPointer (xdpy, timestamp);
    XUngrabKeyboard (xdpy, timestamp);

    display->grab_op = META_GRAB_OP_NONE;
    display->grab_window = NULL;
    display->grab_screen = NULL;
    display->grab_have_pointer = FALSE;
    display->grab_have_keyboard = FALSE;

    compositor->modal_plugin = NULL;
}
static void
sync_unredirected (MetaSurfaceActorX11 *self)
{
  MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self);
  MetaDisplay *display = priv->display;
  Display *xdisplay = meta_display_get_xdisplay (display);
  Window xwindow = meta_window_x11_get_toplevel_xwindow (priv->window);

  meta_error_trap_push (display);

  if (priv->unredirected)
    {
      detach_pixmap (self);
      XCompositeUnredirectWindow (xdisplay, xwindow, CompositeRedirectManual);
    }
  else
    {
      XCompositeRedirectWindow (xdisplay, xwindow, CompositeRedirectManual);
    }

  meta_error_trap_pop (display);
}
Пример #20
0
/*
 * Shapes the cow so that the given window is exposed,
 * when metaWindow is NULL it clears the shape again
 */
static void
meta_shape_cow_for_window (MetaScreen *screen,
                           MetaWindow *metaWindow)
{
    MetaCompScreen *info = meta_screen_get_compositor_data (screen);
    Display *xdisplay = meta_display_get_xdisplay (meta_screen_get_display (screen));

    if (metaWindow == NULL)
        XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);
    else
    {
        XserverRegion output_region;
        XRectangle screen_rect, window_bounds;
        int width, height;
        MetaRectangle rect;

        meta_window_get_outer_rect (metaWindow, &rect);

        window_bounds.x = rect.x;
        window_bounds.y = rect.y;
        window_bounds.width = rect.width;
        window_bounds.height = rect.height;

        meta_screen_get_size (screen, &width, &height);
        screen_rect.x = 0;
        screen_rect.y = 0;
        screen_rect.width = width;
        screen_rect.height = height;

        output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);

        XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
        XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, output_region);
        XFixesDestroyRegion (xdisplay, output_region);
    }
}
Пример #21
0
/**
 * shell_global_set_stage_input_region:
 * @global: the #ShellGlobal
 * @rectangles: (element-type Meta.Rectangle): a list of #MetaRectangle
 * describing the input region.
 *
 * Sets the area of the stage that is responsive to mouse clicks when
 * the stage mode is %SHELL_STAGE_INPUT_MODE_NORMAL (but does not change the
 * current stage mode).
 */
void
shell_global_set_stage_input_region (ShellGlobal *global,
                                     GSList      *rectangles)
{
  MetaScreen *screen = mutter_plugin_get_screen (global->plugin);
  MetaDisplay *display = meta_screen_get_display (screen);
  Display *xdpy = meta_display_get_xdisplay (display);
  MetaRectangle *rect;
  XRectangle *rects;
  int nrects, i;
  GSList *r;

  g_return_if_fail (SHELL_IS_GLOBAL (global));

  nrects = g_slist_length (rectangles);
  rects = g_new (XRectangle, nrects);
  for (r = rectangles, i = 0; r; r = r->next, i++)
    {
      rect = (MetaRectangle *)r->data;
      rects[i].x = rect->x;
      rects[i].y = rect->y;
      rects[i].width = rect->width;
      rects[i].height = rect->height;
    }

  if (global->input_region)
    XFixesDestroyRegion (xdpy, global->input_region);

  global->input_region = XFixesCreateRegion (xdpy, rects, nrects);
  g_free (rects);

  /* set_stage_input_mode() will figure out whether or not we
   * should actually change the input region right now.
   */
  shell_global_set_stage_input_mode (global, global->input_mode);
}
Пример #22
0
/**
 * meta_shape_cow_for_window:
 * @compositor: A #MetaCompositor
 * @window: (nullable): A #MetaWindow to shape the COW for
 *
 * Sets an bounding shape on the COW so that the given window
 * is exposed. If @window is %NULL it clears the shape again.
 *
 * Used so we can unredirect windows, by shaping away the part
 * of the COW, letting the raw window be seen through below.
 */
static void
meta_shape_cow_for_window (MetaCompositor *compositor,
                           MetaWindow *window)
{
  MetaDisplay *display = compositor->display;
  Display *xdisplay = meta_display_get_xdisplay (display);

  if (window == NULL)
    XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, None);
  else
    {
      XserverRegion output_region;
      XRectangle screen_rect, window_bounds;
      int width, height;
      MetaRectangle rect;

      meta_window_get_frame_rect (window, &rect);

      window_bounds.x = rect.x;
      window_bounds.y = rect.y;
      window_bounds.width = rect.width;
      window_bounds.height = rect.height;

      meta_screen_get_size (display->screen, &width, &height);
      screen_rect.x = 0;
      screen_rect.y = 0;
      screen_rect.width = width;
      screen_rect.height = height;

      output_region = XFixesCreateRegion (xdisplay, &window_bounds, 1);

      XFixesInvertRegion (xdisplay, output_region, &screen_rect, output_region);
      XFixesSetWindowShapeRegion (xdisplay, compositor->output, ShapeBounding, 0, 0, output_region);
      XFixesDestroyRegion (xdisplay, output_region);
    }
}
Пример #23
0
void
meta_compositor_sync_screen_size (MetaCompositor  *compositor,
				  guint		   width,
				  guint		   height)
{
  MetaDisplay *display = compositor->display;

  if (meta_is_wayland_compositor ())
    {
      /* FIXME: when we support a sliced stage, this is the place to do it
         But! This is not the place to apply KMS config, here we only
         notify Clutter/Cogl/GL that the framebuffer sizes changed.

         And because for now clutter does not do sliced, we use one
         framebuffer the size of the whole screen, and when running on
         bare metal MetaMonitorManager will do the necessary tricks to
         show the right portions on the right screens.
      */

      clutter_actor_set_size (compositor->stage, width, height);
    }
  else
    {
      Display        *xdisplay;
      Window          xwin;

      xdisplay = meta_display_get_xdisplay (display);
      xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (compositor->stage));

      XResizeWindow (xdisplay, xwin, width, height);
    }

  meta_verbose ("Changed size for stage on screen %d to %dx%d\n",
                meta_screen_get_screen_number (display->screen),
                width, height);
}
Пример #24
0
LOCAL_SYMBOL gboolean
meta_begin_modal_for_plugin (MetaScreen       *screen,
                             MetaPlugin       *plugin,
                             Window            grab_window,
                             Cursor            cursor,
                             MetaModalOptions  options,
                             guint32           timestamp)
{
    /* To some extent this duplicates code in meta_display_begin_grab_op(), but there
     * are significant differences in how we handle grabs that make it difficult to
     * merge the two.
     */
    MetaDisplay    *display    = meta_screen_get_display (screen);
    Display        *xdpy       = meta_display_get_xdisplay (display);
    MetaCompositor *compositor = display->compositor;
    gboolean pointer_grabbed = FALSE;
    gboolean keyboard_grabbed = FALSE;
    int result;

    if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
        return FALSE;

    if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
    {
        result = XGrabPointer (xdpy, grab_window,
                               False, /* owner_events */
                               (ButtonPressMask | ButtonReleaseMask |
                                EnterWindowMask | LeaveWindowMask | PointerMotionMask),
                               GrabModeAsync, GrabModeAsync,
                               None, /* confine to */
                               cursor,
                               timestamp);
        if (result != Success)
            goto fail;

        pointer_grabbed = TRUE;
    }

    if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
    {
        result = XGrabKeyboard (xdpy, grab_window,
                                False, /* owner_events */
                                GrabModeAsync, GrabModeAsync,
                                timestamp);

        if (result != Success)
            goto fail;

        keyboard_grabbed = TRUE;
    }

    display->grab_op = META_GRAB_OP_COMPOSITOR;
    display->grab_window = NULL;
    display->grab_screen = screen;
    display->grab_have_pointer = TRUE;
    display->grab_have_keyboard = TRUE;

    compositor->modal_plugin = plugin;

    return TRUE;

fail:
    if (pointer_grabbed)
        XUngrabPointer (xdpy, timestamp);
    if (keyboard_grabbed)
        XUngrabKeyboard (xdpy, timestamp);

    return FALSE;
}
Пример #25
0
/**
 * meta_background_actor_update:
 * @screen: a #MetaScreen
 *
 * Refetches the _XROOTPMAP_ID property for the root window and updates
 * the contents of the background actor based on that. There's no attempt
 * to optimize out pixmap values that don't change (since a root pixmap
 * could be replaced by with another pixmap with the same ID under some
 * circumstances), so this should only be called when we actually receive
 * a PropertyNotify event for the property.
 */
void
meta_background_actor_update (MetaScreen *screen)
{
  MetaScreenBackground *background;
  MetaDisplay *display;
  MetaCompositor *compositor;
  Atom type;
  int format;
  gulong nitems;
  gulong bytes_after;
  guchar *data;
  Pixmap root_pixmap_id;

  background = meta_screen_background_get (screen);
  display = meta_screen_get_display (screen);
  compositor = meta_display_get_compositor (display);

  root_pixmap_id = None;
  if (!XGetWindowProperty (meta_display_get_xdisplay (display),
                           meta_screen_get_xroot (screen),
                           compositor->atom_x_root_pixmap,
                           0, LONG_MAX,
                           False,
                           AnyPropertyType,
                           &type, &format, &nitems, &bytes_after, &data) &&
      type != None)
  {
     /* Got a property. */
     if (type == XA_PIXMAP && format == 32 && nitems == 1)
       {
         /* Was what we expected. */
         root_pixmap_id = *(Pixmap *)data;
       }

     XFree(data);
  }

  if (root_pixmap_id != None)
    {
      CoglHandle texture;
      CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ());
      GError *error = NULL;

      meta_error_trap_push (display);
      texture = cogl_texture_pixmap_x11_new (ctx, root_pixmap_id, FALSE, &error);
      meta_error_trap_pop (display);

      if (texture != COGL_INVALID_HANDLE)
        {
          set_texture (background, texture);
          cogl_handle_unref (texture);

          background->have_pixmap = True;
          return;
        }
      else
        {
          g_warning ("Failed to create background texture from pixmap: %s",
                     error->message);
          g_error_free (error);
        }
    }

  background->have_pixmap = False;
  set_texture_to_stage_color (background);
}
Пример #26
0
void
meta_compositor_manage_screen (MetaCompositor *compositor,
                               MetaScreen     *screen)
{
    MetaCompScreen *info;
    MetaDisplay    *display       = meta_screen_get_display (screen);
    Display        *xdisplay      = meta_display_get_xdisplay (display);
    int             screen_number = meta_screen_get_screen_number (screen);
    Window          xroot         = meta_screen_get_xroot (screen);
    Window          xwin;
    gint            width, height;
    XWindowAttributes attr;
    long            event_mask;
    guint           n_retries;
    guint           max_retries;

    /* Check if the screen is already managed */
    if (meta_screen_get_compositor_data (screen))
        return;

    if (meta_get_replace_current_wm ())
        max_retries = 5;
    else
        max_retries = 1;

    n_retries = 0;

    /* Some compositors (like old versions of Muffin) might not properly unredirect
     * subwindows before destroying the WM selection window; so we wait a while
     * for such a compositor to exit before giving up.
     */
    while (TRUE)
    {
        meta_error_trap_push_with_return (display);
        XCompositeRedirectSubwindows (xdisplay, xroot, CompositeRedirectManual);
        XSync (xdisplay, FALSE);

        if (!meta_error_trap_pop_with_return (display))
            break;

        if (n_retries == max_retries)
        {
            /* This probably means that a non-WM compositor like xcompmgr is running;
             * we have no way to get it to exit */
            meta_fatal (_("Another compositing manager is already running on screen %i on display \"%s\"."),
                        screen_number, display->name);
        }

        n_retries++;
        g_usleep (G_USEC_PER_SEC);
    }

    info = g_new0 (MetaCompScreen, 1);
    /*
     * We use an empty input region for Clutter as a default because that allows
     * the user to interact with all the windows displayed on the screen.
     * We have to initialize info->pending_input_region to an empty region explicitly,
     * because None value is used to mean that the whole screen is an input region.
     */
    info->pending_input_region = XFixesCreateRegion (xdisplay, NULL, 0);

    info->screen = screen;

    meta_screen_set_compositor_data (screen, info);

    info->output = None;
    info->windows = NULL;

    meta_screen_set_cm_selection (screen);

    info->stage = clutter_stage_new ();

    meta_screen_get_size (screen, &width, &height);
    clutter_actor_realize (info->stage);

    xwin = clutter_x11_get_stage_window (CLUTTER_STAGE (info->stage));

    XResizeWindow (xdisplay, xwin, width, height);

    event_mask = FocusChangeMask |
                 ExposureMask |
                 EnterWindowMask | LeaveWindowMask |
                 PointerMotionMask |
                 PropertyChangeMask |
                 ButtonPressMask | ButtonReleaseMask |
                 KeyPressMask | KeyReleaseMask |
                 StructureNotifyMask;

    if (XGetWindowAttributes (xdisplay, xwin, &attr))
    {
        event_mask |= attr.your_event_mask;
    }

    XSelectInput (xdisplay, xwin, event_mask);

    info->window_group = meta_window_group_new (screen);
    info->background_actor = meta_background_actor_new_for_screen (screen);
    info->bottom_window_group = clutter_group_new();
    info->overlay_group = clutter_group_new ();
    info->top_window_group = meta_window_group_new (screen);
    info->hidden_group = clutter_group_new ();

    clutter_container_add (CLUTTER_CONTAINER (info->window_group),
                           info->background_actor,
                           NULL);

    clutter_container_add (CLUTTER_CONTAINER (info->stage),
                           info->window_group,
                           info->overlay_group,
                           info->hidden_group,
                           NULL);

    clutter_actor_hide (info->hidden_group);

    info->plugin_mgr =
        meta_plugin_manager_get (screen);
    meta_plugin_manager_initialize (info->plugin_mgr);

    /*
     * Delay the creation of the overlay window as long as we can, to avoid
     * blanking out the screen. This means that during the plugin loading, the
     * overlay window is not accessible; if the plugin needs to access it
     * directly, it should hook into the "show" signal on stage, and do
     * its stuff there.
     */
    info->output = get_output_window (screen);
    XReparentWindow (xdisplay, xwin, info->output, 0, 0);

    /* Make sure there isn't any left-over output shape on the
     * overlay window by setting the whole screen to be an
     * output region.
     *
     * Note: there doesn't seem to be any real chance of that
     *  because the X server will destroy the overlay window
     *  when the last client using it exits.
     */
    XFixesSetWindowShapeRegion (xdisplay, info->output, ShapeBounding, 0, 0, None);

    do_set_stage_input_region (screen, info->pending_input_region);
    if (info->pending_input_region != None)
    {
        XFixesDestroyRegion (xdisplay, info->pending_input_region);
        info->pending_input_region = None;
    }

    clutter_actor_show (info->overlay_group);
    clutter_actor_show (info->stage);
}