Пример #1
0
static void
set_active_space_hint (MetaScreen *screen)
{
  unsigned long data[1];

  /* this is because we destroy the spaces in order,
   * so we always end up setting a current desktop of
   * 0 when closing a screen, so lose the current desktop
   * on restart. By doing this we keep the current
   * desktop on restart.
   */
  if (screen->closing > 0)
    return;

  data[0] = meta_workspace_index (screen->active_workspace);

  meta_verbose ("Setting _NET_CURRENT_DESKTOP to %lu\n", data[0]);

  meta_error_trap_push (screen->display);
  XChangeProperty (screen->display->xdisplay, screen->xroot,
                   screen->display->atom__NET_CURRENT_DESKTOP,
                   XA_CARDINAL,
                   32, PropModeReplace, (guchar*) data, 1);
  meta_error_trap_pop (screen->display, FALSE);
}
Пример #2
0
void
meta_core_lower_beneath_focus_window (Display *xdisplay,
                                      Window xwindow,
                                      guint32 timestamp)
{
  XWindowChanges changes;
  MetaDisplay *display;
  MetaScreen *screen;
  MetaWindow *focus_window;

  display = meta_display_for_x_display (xdisplay);
  screen = meta_display_screen_for_xwindow (display, xwindow);
  focus_window = meta_stack_get_top (screen->stack);

  if (focus_window == NULL)
    return;

  changes.stack_mode = Below;
  changes.sibling = focus_window->frame ? focus_window->frame->xwindow
                                        : focus_window->xwindow;

  meta_error_trap_push (display);
  XConfigureWindow (xdisplay,
                    xwindow,
                    CWSibling | CWStackMode,
                    &changes);
  meta_error_trap_pop (display, FALSE);
}
Пример #3
0
void
meta_window_kill (MetaWindow *window)
{
  meta_topic (META_DEBUG_WINDOW_OPS,
              "Killing %s brutally\n",
              window->desc);

  if (!meta_window_is_remote (window) &&
      window->net_wm_pid > 0)
    {
      meta_topic (META_DEBUG_WINDOW_OPS,
                  "Killing %s with kill()\n",
                  window->desc);

      if (kill (window->net_wm_pid, 9) < 0)
        meta_topic (META_DEBUG_WINDOW_OPS,
                    "Failed to signal %s: %s\n",
                    window->desc, strerror (errno));
    }

  meta_topic (META_DEBUG_WINDOW_OPS,
              "Disconnecting %s with XKillClient()\n",
              window->desc);
  meta_error_trap_push (window->display);
  XKillClient (window->display->xdisplay, window->xwindow);
  meta_error_trap_pop (window->display);
}
Пример #4
0
LOCAL_SYMBOL void
meta_core_lower_beneath_sibling (Display   *xdisplay,
                                 Window     xwindow,
                                 Window     grab_window,
                                 guint32    timestamp)
{
  XWindowChanges changes;
  MetaDisplay *display;
  MetaScreen *screen;

  display = meta_display_for_x_display (xdisplay);
  screen = meta_display_screen_for_xwindow (display, xwindow);

  changes.stack_mode = Below;
  changes.sibling = grab_window;

  meta_stack_tracker_record_lower_below (screen->stack_tracker,
                                         xwindow,
                                         changes.sibling,
                                         XNextRequest (screen->display->xdisplay));

  meta_error_trap_push (display);
  XConfigureWindow (xdisplay,
                    xwindow,
                    CWSibling | CWStackMode,
                    &changes);
  meta_error_trap_pop (display);
}
Пример #5
0
void
meta_window_delete (MetaWindow  *window,
                    guint32      timestamp)
{
  meta_error_trap_push (window->display);
  if (window->delete_window)
    {
      meta_topic (META_DEBUG_WINDOW_OPS,
                  "Deleting %s with delete_window request\n",
                  window->desc);
      meta_window_send_icccm_message (window,
                                      window->display->atom_WM_DELETE_WINDOW,
                                      timestamp);
    }
  else
    {
      meta_topic (META_DEBUG_WINDOW_OPS,
                  "Deleting %s with explicit kill\n",
                  window->desc);
      XKillClient (window->display->xdisplay, window->xwindow);
    }
  meta_error_trap_pop (window->display);

  meta_display_ping_window (window->display,
                            window,
                            timestamp,
                            delete_ping_reply_func,
                            delete_ping_timeout_func,
                            window);
}
Пример #6
0
void
meta_core_lower_beneath_grab_window (Display *xdisplay,
                                     Window   xwindow,
                                     guint32  timestamp)
{
  XWindowChanges changes;
  MetaDisplay *display;
  MetaScreen *screen;
  MetaWindow *grab_window;

  display = meta_display_for_x_display (xdisplay);
  screen = meta_display_screen_for_xwindow (display, xwindow);
  grab_window = display->grab_window;

  if (grab_window == NULL)
    return;

  changes.stack_mode = Below;
  changes.sibling = grab_window->frame ? grab_window->frame->xwindow
                                       : grab_window->xwindow;

  meta_stack_tracker_record_lower_below (screen->stack_tracker,
                                         xwindow,
                                         changes.sibling,
                                         XNextRequest (screen->display->xdisplay));

  meta_error_trap_push (display);
  XConfigureWindow (xdisplay,
                    xwindow,
                    CWSibling | CWStackMode,
                    &changes);
  meta_error_trap_pop (display);
}
Пример #7
0
gboolean
meta_frame_sync_to_window (MetaFrame *frame,
                           int        resize_gravity,
                           gboolean   need_move,
                           gboolean   need_resize)
{
  if (!(need_move || need_resize))
    {
      return update_shape (frame);
    }

  meta_topic (META_DEBUG_GEOMETRY,
              "Syncing frame geometry %d,%d %dx%d (SE: %d,%d)\n",
              frame->rect.x, frame->rect.y,
              frame->rect.width, frame->rect.height,
              frame->rect.x + frame->rect.width,
              frame->rect.y + frame->rect.height);

  /* set bg to none to avoid flicker */
  if (need_resize)
    {
      /* we need new shape if we're resized */
      frame->need_reapply_frame_shape = TRUE;
    }

  /* Done before the window resize, because doing it before means
   * part of the window being resized becomes unshaped, which may
   * be sort of hard to see with bg = None. If we did it after
   * window resize, part of the window being resized would become
   * shaped, which might be more visible.
   */
  update_shape (frame);

  /* this may fail because of extra large size change, I dont have
   * a better solution now 
   * */
  meta_error_trap_push (frame->window->display);
  meta_ui_move_resize_frame (frame->window->screen->ui,
			     frame->xwindow,
			     frame->rect.x,
			     frame->rect.y,
			     frame->rect.width,
			     frame->rect.height);

  meta_error_trap_pop (frame->window->display, FALSE);

  if (need_resize)
    {
      /* If we're interactively resizing the frame, repaint
       * it immediately so we don't start to lag.
       */
      if (frame->window->display->grab_window ==
          frame->window)
        meta_ui_repaint_frame (frame->window->screen->ui,
                               frame->xwindow);
    }

  return need_resize;
}
Пример #8
0
void
meta_window_delete (MetaWindow  *window,
                    guint32      timestamp)
{
  meta_error_trap_push (window->display);
  if (window->delete_window)
    {
      meta_topic (META_DEBUG_WINDOW_OPS,
                  "Deleting %s with delete_window request\n",
                  window->desc);
      meta_window_send_icccm_message (window,
                                      window->display->atom_WM_DELETE_WINDOW,
                                      timestamp);
    }
  else
    {
      meta_topic (META_DEBUG_WINDOW_OPS,
                  "Deleting %s with explicit kill\n",
                  window->desc);
      XKillClient (window->display->xdisplay, window->xwindow);
    }
  meta_error_trap_pop (window->display, FALSE);

  meta_display_ping_window (window->display,
                            window,
                            timestamp,
                            delete_ping_reply_func,
                            delete_ping_timeout_func,
                            window);
  
  if (window->has_focus)
    {
      /* FIXME Clean this up someday 
       * http://bugzilla.gnome.org/show_bug.cgi?id=108706
       */
#if 0
      /* This is unfortunately going to result in weirdness
       * if the window doesn't respond to the delete event.
       * I don't know how to avoid that though.
       */
      meta_topic (META_DEBUG_FOCUS,
                  "Focusing default window because focus window %s was deleted/killed\n",
                  window->desc);
      meta_workspace_focus_default_window (window->screen->active_workspace,
                                           window);
#else
      meta_topic (META_DEBUG_FOCUS,
                  "Not unfocusing %s on delete/kill\n",
                  window->desc);
#endif
    }
  else
    {
      meta_topic (META_DEBUG_FOCUS,
                  "Window %s was deleted/killed but didn't have focus\n",
                  window->desc);
    }
}
Пример #9
0
void
meta_window_destroy_frame (MetaWindow *window)
{
  MetaFrame *frame;

  if (window->frame == NULL)
    return;

  meta_verbose ("Unframing window %s\n", window->desc);

  frame = window->frame;

  meta_bell_notify_frame_destroy (frame);

  /* Unparent the client window; it may be destroyed,
   * thus the error trap.
   */
  meta_error_trap_push (window->display);
  if (window->mapped)
    {
      window->mapped = FALSE; /* Keep track of unmapping it, so we
                               * can identify a withdraw initiated
                               * by the client.
                               */
      meta_topic (META_DEBUG_WINDOW_STATE,
                  "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
      window->unmaps_pending += 1;
    }
  XReparentWindow (window->display->xdisplay,
                   window->xwindow,
                   window->screen->xroot,
                   /* Using anything other than meta_window_get_position()
                    * coordinates here means we'll need to ensure a configure
                    * notify event is sent; see bug 399552.
                    */
                   window->frame->rect.x,
                   window->frame->rect.y);
  meta_error_trap_pop (window->display, FALSE);

  meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow);

  meta_display_unregister_x_window (window->display,
                                    frame->xwindow);

  window->frame = NULL;

  /* Move keybindings to window instead of frame */
  meta_window_grab_keys (window);

  g_free (frame);

  /* Put our state back where it should be */
  meta_window_queue (window, META_QUEUE_CALC_SHOWING);
  meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
}
Пример #10
0
void
meta_compositor_add_window (MetaCompositor    *compositor,
                            MetaWindow        *window)
{
  MetaDisplay *display = compositor->display;

  meta_error_trap_push (display);

  meta_window_actor_new (window);
  sync_actor_stacking (compositor);

  meta_error_trap_pop (display);
}
void
meta_prop_set_utf8_string_hint (MetaDisplay *display,
                                Window xwindow,
                                Atom atom,
                                const char *val)
{
  meta_error_trap_push (display);
  XChangeProperty (display->xdisplay, 
                   xwindow, atom,
                   display->atom_UTF8_STRING, 
                   8, PropModeReplace, (guchar*) val, strlen (val));
  meta_error_trap_pop (display, FALSE);
}
Пример #12
0
void
meta_compositor_add_window (MetaCompositor    *compositor,
                            MetaWindow        *window)
{
    MetaScreen *screen = meta_window_get_screen (window);
    MetaDisplay *display = meta_screen_get_display (screen);

    DEBUG_TRACE ("meta_compositor_add_window\n");
    meta_error_trap_push (display);

    add_win (window);

    meta_error_trap_pop (display);
}
Пример #13
0
static void
set_texture_on_actor (MetaBackgroundActor *self)
{
  MetaBackgroundActorPrivate *priv = self->priv;
  MetaDisplay *display = meta_screen_get_display (priv->background->screen);

  /* This may trigger destruction of an old texture pixmap, which, if
   * the underlying X pixmap is already gone has the tendency to trigger
   * X errors inside DRI. For safety, trap errors */
  meta_error_trap_push (display);
  cogl_material_set_layer (priv->material, 0, priv->background->texture);
  meta_error_trap_pop (display);

  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
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);
}
Пример #15
0
void
meta_background_set_layer (MetaBackground *self,
                           CoglHandle      texture)
{
  MetaBackgroundPrivate *priv = self->priv;
  MetaDisplay *display = meta_screen_get_display (priv->screen);

  /* This may trigger destruction of an old texture pixmap, which, if
   * the underlying X pixmap is already gone has the tendency to trigger
   * X errors inside DRI. For safety, trap errors */
  meta_error_trap_push (display);
  cogl_material_set_layer (priv->material, 0, texture);
  meta_error_trap_pop (display);

  priv->texture_width = cogl_texture_get_width (texture);
  priv->texture_height = cogl_texture_get_height (texture);

  clutter_actor_queue_redraw (CLUTTER_ACTOR (self));
}
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);
}
Пример #18
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);
    }
}
Пример #19
0
void
meta_window_kill (MetaWindow *window)
{
  char buf[257];
  
  meta_topic (META_DEBUG_WINDOW_OPS,
              "Killing %s brutally\n",
              window->desc);

  if (window->wm_client_machine != NULL &&
      window->net_wm_pid > 0)
    {
      if (gethostname (buf, sizeof(buf)-1) == 0)
        {
          if (strcmp (buf, window->wm_client_machine) == 0)
            {
              meta_topic (META_DEBUG_WINDOW_OPS,
                          "Killing %s with kill()\n",
                          window->desc);

              if (kill (window->net_wm_pid, 9) < 0)
                meta_topic (META_DEBUG_WINDOW_OPS,
                            "Failed to signal %s: %s\n",
                            window->desc, strerror (errno));
            }
        }
      else
        {
          meta_warning (_("Failed to get hostname: %s\n"),
                        strerror (errno));
        }
    }
  
  meta_topic (META_DEBUG_WINDOW_OPS,
              "Disconnecting %s with XKillClient()\n",
              window->desc);
  meta_error_trap_push (window->display);
  XKillClient (window->display->xdisplay, window->xwindow);
  meta_error_trap_pop (window->display, FALSE);
}
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);
}
Пример #21
0
void
meta_window_ensure_frame (MetaWindow *window)
{
  MetaFrame *frame;
  XSetWindowAttributes attrs;
  gulong create_serial;

  if (window->frame)
    return;

  frame = g_new (MetaFrame, 1);

  frame->window = window;
  frame->xwindow = None;

  frame->rect = window->rect;
  frame->child_x = 0;
  frame->child_y = 0;
  frame->bottom_height = 0;
  frame->right_width = 0;
  frame->current_cursor = 0;

  frame->is_flashing = FALSE;
  frame->borders_cached = FALSE;

  meta_verbose ("Frame geometry %d,%d  %dx%d\n",
                frame->rect.x, frame->rect.y,
                frame->rect.width, frame->rect.height);

  frame->ui_frame = meta_ui_create_frame (window->screen->ui,
                                          window->display->xdisplay,
                                          frame->window,
                                          window->xvisual,
                                          frame->rect.x,
                                          frame->rect.y,
                                          frame->rect.width,
                                          frame->rect.height,
                                          &create_serial);
  frame->xwindow = frame->ui_frame->xwindow;

  meta_stack_tracker_record_add (window->screen->stack_tracker,
                                 frame->xwindow,
                                 create_serial);

  meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
  attrs.event_mask = EVENT_MASK;
  XChangeWindowAttributes (window->display->xdisplay,
			   frame->xwindow, CWEventMask, &attrs);

  meta_display_register_x_window (window->display, &frame->xwindow, window);

  meta_error_trap_push (window->display);
  if (window->mapped)
    {
      window->mapped = FALSE; /* the reparent will unmap the window,
                               * we don't want to take that as a withdraw
                               */
      meta_topic (META_DEBUG_WINDOW_STATE,
                  "Incrementing unmaps_pending on %s for reparent\n", window->desc);
      window->unmaps_pending += 1;
    }

  meta_stack_tracker_record_remove (window->screen->stack_tracker,
                                    window->xwindow,
                                    XNextRequest (window->display->xdisplay));
  XReparentWindow (window->display->xdisplay,
                   window->xwindow,
                   frame->xwindow,
                   frame->child_x,
                   frame->child_y);
  /* FIXME handle this error */
  meta_error_trap_pop (window->display);

  /* stick frame to the window */
  window->frame = frame;

  /* Now that frame->xwindow is registered with window, we can set its
   * style and background.
   */
  meta_frame_update_style (frame);
  meta_frame_update_title (frame);

  meta_ui_map_frame (frame->window->screen->ui, frame->xwindow);

  {
    MetaBackend *backend = meta_get_backend ();
    if (META_IS_BACKEND_X11 (backend))
      {
        Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend));

        /* Since the backend selects for events on another connection,
         * make sure to sync the GTK+ connection to ensure that the
         * frame window has been created on the server at this point. */
        XSync (window->display->xdisplay, False);

        unsigned char mask_bits[XIMaskLen (XI_LASTEVENT)] = { 0 };
        XIEventMask mask = { XIAllMasterDevices, sizeof (mask_bits), mask_bits };

        XISelectEvents (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
                        frame->xwindow, &mask, 1);

        XISetMask (mask.mask, XI_ButtonPress);
        XISetMask (mask.mask, XI_ButtonRelease);
        XISetMask (mask.mask, XI_Motion);
        XISetMask (mask.mask, XI_Enter);
        XISetMask (mask.mask, XI_Leave);

        XISelectEvents (xdisplay, frame->xwindow, &mask, 1);
      }
  }

  /* Move keybindings to frame instead of window */
  meta_window_grab_keys (window);
}
Пример #22
0
/**
 * This function is used to avoid raising a window above popup
 * menus and other such things.
 *
 * FIXME This is sort of an expensive function, should probably
 * do something to avoid it. One approach would be to reverse
 * the stacking algorithm to work by placing each window above
 * the others, and start by lowering a window to the bottom
 * (instead of the current way, which works by placing each
 * window below another and starting with a raise)
 */
static void
raise_window_relative_to_managed_windows (MetaScreen *screen,
                                          Window      xwindow)
{

  Window ignored1, ignored2;
  Window *children;
  unsigned int n_children;
  int i;

  /* Normally XQueryTree() means "must grab server" but here
   * we don't, since we know we won't manage any new windows
   * or restack any windows before using the XQueryTree results.
   */
  
  meta_error_trap_push_with_return (screen->display);
  
  XQueryTree (screen->display->xdisplay,
              screen->xroot,
              &ignored1, &ignored2, &children, &n_children);

  if (meta_error_trap_pop_with_return (screen->display, TRUE) != Success)
    {
      meta_topic (META_DEBUG_STACK,
                  "Error querying root children to raise window 0x%lx\n",
                  xwindow);
      return;
    }

  /* Children are in order from bottom to top. We want to
   * find the topmost managed child, then configure
   * our window to be above it.
   */
  i = n_children - 1;
  while (i >= 0)
    {
      if (children[i] == xwindow)
        {
          /* Do nothing. This means we're already the topmost managed
           * window, but it DOES NOT mean we are already just above
           * the topmost managed window. This is important because if
           * an override redirect window is up, and we map a new
           * managed window, the new window is probably above the old
           * popup by default, and we want to push it below that
           * popup. So keep looking for a sibling managed window
           * to be moved below.
           */
        }
      else if (meta_display_lookup_x_window (screen->display,
                                             children[i]) != NULL)
        {
          XWindowChanges changes;
          
          /* children[i] is the topmost managed child */
          meta_topic (META_DEBUG_STACK,
                      "Moving 0x%lx above topmost managed child window 0x%lx\n",
                      xwindow, children[i]);

          changes.sibling = children[i];
          changes.stack_mode = Above;

          meta_error_trap_push (screen->display);
          XConfigureWindow (screen->display->xdisplay,
                            xwindow,
                            CWSibling | CWStackMode,
                            &changes);
          meta_error_trap_pop (screen->display, FALSE);

          break;
        }

      --i;
    }

  if (i < 0)
    {
      /* No sibling to use, just lower ourselves to the bottom
       * to be sure we're below any override redirect windows.
       */
      meta_error_trap_push (screen->display);
      XLowerWindow (screen->display->xdisplay,
                    xwindow);
      meta_error_trap_pop (screen->display, FALSE);
    }
  
  if (children)
    XFree (children);
}
static gboolean
validate_or_free_results (GetPropertyResults *results,
                          int                 expected_format,
                          Atom                expected_type,
                          gboolean            must_have_items)
{
  char *type_name;
  char *expected_name;
  char *prop_name;
  const char *title;
  const char *res_class;
  const char *res_name;
  MetaWindow *w;
  
  if (expected_format == results->format &&
      expected_type == results->type &&
      (!must_have_items || results->n_items > 0))
    return TRUE;  
  
  meta_error_trap_push (results->display);
  type_name = XGetAtomName (results->display->xdisplay, results->type);
  expected_name = XGetAtomName (results->display->xdisplay, expected_type);
  prop_name = XGetAtomName (results->display->xdisplay, results->xatom);
  meta_error_trap_pop (results->display, TRUE);

  w = meta_display_lookup_x_window (results->display, results->xwindow);

  if (w != NULL)
    {
      title = w->title;
      res_class = w->res_class;
      res_name = w->res_name;
    }
  else
    {
      title = NULL;
      res_class = NULL;
      res_name = NULL;
    }
  
  if (title == NULL)
    title = "unknown";

  if (res_class == NULL)
    res_class = "unknown";

  if (res_name == NULL)
    res_name = "unknown";
  
  meta_warning (_("Window 0x%lx has property %s\nthat was expected to have type %s format %d\nand actually has type %s format %d n_items %d.\nThis is most likely an application bug, not a window manager bug.\nThe window has title=\"%s\" class=\"%s\" name=\"%s\"\n"),
                results->xwindow,
                prop_name ? prop_name : "(bad atom)",
                expected_name ? expected_name : "(bad atom)",
                expected_format,
                type_name ? type_name : "(bad atom)",
                results->format, (int) results->n_items,
                title, res_class, res_name);

  if (type_name)
    XFree (type_name);
  if (expected_name)
    XFree (expected_name);
  if (prop_name)
    XFree (prop_name);

  if (results->prop)
    {
      XFree (results->prop);
      results->prop = NULL;
    }
  
  return FALSE;
}
Пример #24
0
void
meta_window_destroy_frame (MetaWindow *window)
{
  MetaFrame *frame;
  MetaFrameBorders borders;

  if (window->frame == NULL)
    return;

  meta_verbose ("Unframing window %s\n", window->desc);

  frame = window->frame;

  meta_frame_calc_borders (frame, &borders);

  meta_bell_notify_frame_destroy (frame);

  /* Unparent the client window; it may be destroyed,
   * thus the error trap.
   */
  meta_error_trap_push (window->display);
  if (window->mapped)
    {
      window->mapped = FALSE; /* Keep track of unmapping it, so we
                               * can identify a withdraw initiated
                               * by the client.
                               */
      meta_topic (META_DEBUG_WINDOW_STATE,
                  "Incrementing unmaps_pending on %s for reparent back to root\n", window->desc);
      window->unmaps_pending += 1;
    }
  meta_stack_tracker_record_add (window->screen->stack_tracker,
                                 window->xwindow,
                                 XNextRequest (window->display->xdisplay));
  XReparentWindow (window->display->xdisplay,
                   window->xwindow,
                   window->screen->xroot,
                   /* Using anything other than client root window coordinates
                    * coordinates here means we'll need to ensure a configure
                    * notify event is sent; see bug 399552.
                    */
                   window->frame->rect.x + borders.invisible.left,
                   window->frame->rect.y + borders.invisible.top);
  meta_error_trap_pop (window->display);

  meta_ui_frame_unmanage (frame->ui_frame);

  meta_display_unregister_x_window (window->display,
                                    frame->xwindow);

  window->frame = NULL;
  if (window->frame_bounds)
    {
      cairo_region_destroy (window->frame_bounds);
      window->frame_bounds = NULL;
    }

  /* Move keybindings to window instead of frame */
  meta_window_grab_keys (window);

  g_free (frame);

  /* Put our state back where it should be */
  meta_window_queue (window, META_QUEUE_CALC_SHOWING);
  meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
}
/* this one freakishly returns g_malloc memory */
static gboolean
utf8_list_from_results (GetPropertyResults *results,
                        char             ***str_p,
                        int                *n_str_p)
{
  int i;
  int n_strings;
  char **retval;
  const char *p;
  
  *str_p = NULL;
  *n_str_p = 0;

  if (!validate_or_free_results (results, 8,
                                 results->display->atom_UTF8_STRING, FALSE))
    return FALSE;
  
  /* I'm not sure this is right, but I'm guessing the
   * property is nul-separated
   */
  i = 0;
  n_strings = 0;
  while (i < (int) results->n_items)
    {
      if (results->prop[i] == '\0')
        ++n_strings;
      ++i;
    }

  if (results->prop[results->n_items - 1] != '\0')
    ++n_strings;
 
  /* we're guaranteed that results->prop has a nul on the end
   * by XGetWindowProperty
   */
  
  retval = g_new0 (char*, n_strings + 1);

  p = (char *)results->prop;
  i = 0;
  while (i < n_strings)
    {
      if (!g_utf8_validate (p, -1, NULL))
        {
          char *name;

          meta_error_trap_push (results->display);
          name = XGetAtomName (results->display->xdisplay, results->xatom);
          meta_error_trap_pop (results->display, TRUE);
          meta_warning (_("Property %s on window 0x%lx contained invalid UTF-8 for item %d in the list\n"),
                        name, results->xwindow, i);
          meta_XFree (name);
          meta_XFree (results->prop);
          results->prop = NULL;
          
          g_strfreev (retval);
          return FALSE;
        }

      retval[i] = g_strdup (p);
      
      p = p + strlen (p) + 1;
      ++i;
    }
  
  *str_p = retval;
  *n_str_p = i;

  meta_XFree (results->prop);
  results->prop = NULL;

  return TRUE;
}
Пример #26
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);
}
Пример #27
0
/*
 * This function is used to avoid raising a window above popup
 * menus and other such things.
 *
 * The key to the operation of this function is that we are expecting
 * at most one window to be added at a time. If xwindow is newly added,
 * then its own stack position will be too high (the frame window
 * is created at the top of the stack), but if we ignore xwindow,
 * then the *next* managed window in the stack will be a window that
 * we've already stacked.
 *
 * We could generalize this and remove the assumption that windows
 * are added one at a time by keeping an explicit ->stacked flag in
 * MetaWindow.
 *
 * An alternate approach would be to reverse the stacking algorithm to
 * work by placing each window above the others, and start by lowering
 * a window to the bottom (instead of the current way, which works by
 * placing each window below another and starting with a raise)
 */
static void
raise_window_relative_to_managed_windows (MetaScreen *screen,
                                          Window      xwindow)
{

  Window *children;
  int n_children;
  int i;

  meta_stack_tracker_get_stack (screen->stack_tracker,
                                &children, &n_children);

  /* Children are in order from bottom to top. We want to
   * find the topmost managed child, then configure
   * our window to be above it.
   */
  i = n_children - 1;
  while (i >= 0)
    {
      if (children[i] == xwindow)
        {
          /* Do nothing. This means we're already the topmost managed
           * window, but it DOES NOT mean we are already just above
           * the topmost managed window. This is important because if
           * an override redirect window is up, and we map a new
           * managed window, the new window is probably above the old
           * popup by default, and we want to push it below that
           * popup. So keep looking for a sibling managed window
           * to be moved below.
           */
        }
      else
        {
          MetaWindow *other = meta_display_lookup_x_window (screen->display,
                                                            children[i]);
          if (other != NULL && !other->override_redirect && !other->unmanaging)
            {
              XWindowChanges changes;

              /* children[i] is the topmost managed child */
              meta_topic (META_DEBUG_STACK,
                          "Moving 0x%lx above topmost managed child window 0x%lx\n",
                          xwindow, children[i]);

              changes.sibling = children[i];
              changes.stack_mode = Above;

              meta_error_trap_push (screen->display);
              meta_stack_tracker_record_raise_above (screen->stack_tracker,
                                                     xwindow,
                                                     children[i],
                                                     XNextRequest (screen->display->xdisplay));
              XConfigureWindow (screen->display->xdisplay,
                                xwindow,
                                CWSibling | CWStackMode,
                                &changes);
              meta_error_trap_pop (screen->display);

              break;
            }
        }

      --i;
    }

  if (i < 0)
    {
      /* No sibling to use, just lower ourselves to the bottom
       * to be sure we're below any override redirect windows.
       */
      meta_error_trap_push (screen->display);
      meta_stack_tracker_record_lower (screen->stack_tracker,
                                       xwindow,
                                       XNextRequest (screen->display->xdisplay));
      XLowerWindow (screen->display->xdisplay,
                    xwindow);
      meta_error_trap_pop (screen->display);
    }
}
Пример #28
0
/*
 * Order the windows on the X server to be the same as in our structure.
 * We do this using XRestackWindows if we don't know the previous order,
 * or XConfigureWindow on a few particular windows if we do and can figure
 * out the minimum set of changes.  After that, we set __NET_CLIENT_LIST
 * and __NET_CLIENT_LIST_STACKING.
 *
 * FIXME: Now that we have a good view of the stacking order on the server
 * with MetaStackTracker it should be possible to do a simpler and better
 * job of computing the minimal set of stacking requests needed.
 */
static void
stack_sync_to_server (MetaStack *stack)
{
  GArray *stacked;
  GArray *root_children_stacked;
  GList *tmp;
  GArray *all_hidden;
  int n_override_redirect = 0;
  int n_unmanaging = 0;
  
  /* Bail out if frozen */
  if (stack->freeze_count > 0)
    return;
  
  meta_topic (META_DEBUG_STACK, "Syncing window stack to server\n");  

  stack_ensure_sorted (stack);

  /* Create stacked xwindow arrays.
   * Painfully, "stacked" is in bottom-to-top order for the
   * _NET hints, and "root_children_stacked" is in top-to-bottom
   * order for XRestackWindows()
   */
  stacked = g_array_new (FALSE, FALSE, sizeof (Window));
  root_children_stacked = g_array_new (FALSE, FALSE, sizeof (Window));
  all_hidden = g_array_new (FALSE, FALSE, sizeof (Window));

  /* The screen guard window sits above all hidden windows and acts as
   * a barrier to input reaching these windows. */
  g_array_append_val (all_hidden, stack->screen->guard_window);

  meta_topic (META_DEBUG_STACK, "Top to bottom: ");
  meta_push_no_msg_prefix ();

  for (tmp = stack->sorted; tmp != NULL; tmp = tmp->next)
    {
      MetaWindow *w = tmp->data;
      Window top_level_window;

      if (w->unmanaging)
        {
          n_unmanaging ++;
          continue;
        }
      
      meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
		  w->layer, w->stack_position, w->desc);

      /* remember, stacked is in reverse order (bottom to top) */
      if (w->override_redirect)
	n_override_redirect++;
      else
	g_array_prepend_val (stacked, w->xwindow);
      
      if (w->frame)
	top_level_window = w->frame->xwindow;
      else
	top_level_window = w->xwindow;

      /* We don't restack hidden windows along with the rest, though they are
       * reflected in the _NET hints. Hidden windows all get pushed below
       * the screens fullscreen guard_window. */
      if (w->hidden)
	{
	  g_array_append_val (all_hidden, top_level_window);
	  continue;
	}

      /* build XRestackWindows() array from top to bottom */
      g_array_append_val (root_children_stacked, top_level_window);
    }

  meta_topic (META_DEBUG_STACK, "\n");
  meta_pop_no_msg_prefix ();

  /* All windows should be in some stacking order */
  if (stacked->len != stack->windows->len - n_override_redirect - n_unmanaging)
    meta_bug ("%u windows stacked, %u windows exist in stack\n",
              stacked->len, stack->windows->len);
  
  /* Sync to server */

  meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
              root_children_stacked->len);
  
  meta_error_trap_push (stack->screen->display);

  if (stack->last_root_children_stacked == NULL)
    {
      /* Just impose our stack, we don't know the previous state.
       * This involves a ton of circulate requests and may flicker.
       */
      meta_topic (META_DEBUG_STACK, "Don't know last stack state, restacking everything\n");

      if (root_children_stacked->len > 0)
        {
          meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
                                                     (Window *) root_children_stacked->data,
                                                     root_children_stacked->len,
                                                     XNextRequest (stack->screen->display->xdisplay));
          XRestackWindows (stack->screen->display->xdisplay,
                           (Window *) root_children_stacked->data,
                           root_children_stacked->len);
        }
    }
  else if (root_children_stacked->len > 0)
    {
      /* Try to do minimal window moves to get the stack in order */
      /* A point of note: these arrays include frames not client windows,
       * so if a client window has changed frame since last_root_children_stacked
       * was saved, then we may have inefficiency, but I don't think things
       * break...
       */
      const Window *old_stack = (Window *) stack->last_root_children_stacked->data;
      const Window *new_stack = (Window *) root_children_stacked->data;
      const int old_len = stack->last_root_children_stacked->len;
      const int new_len = root_children_stacked->len;
      const Window *oldp = old_stack;
      const Window *newp = new_stack;
      const Window *old_end = old_stack + old_len;
      const Window *new_end = new_stack + new_len;
      Window last_window = None;
      
      while (oldp != old_end &&
             newp != new_end)
        {
          if (*oldp == *newp)
            {
              /* Stacks are the same here, move on */
              ++oldp;
              last_window = *newp;
              ++newp;
            }
          else if (meta_display_lookup_x_window (stack->screen->display,
                                                 *oldp) == NULL)
            {
              /* *oldp is no longer known to us (probably destroyed),
               * so we can just skip it
               */
              ++oldp;
            }
          else
            {
              /* Move *newp below last_window */
              if (last_window == None)
                {
                  meta_topic (META_DEBUG_STACK, "Using window 0x%lx as topmost (but leaving it in-place)\n", *newp);

                  raise_window_relative_to_managed_windows (stack->screen,
                                                            *newp);
                }
              else
                {
                  /* This means that if last_window is dead, but not
                   * *newp, then we fail to restack *newp; but on
                   * unmanaging last_window, we'll fix it up.
                   */
                  
                  XWindowChanges changes;

                  changes.sibling = last_window;
                  changes.stack_mode = Below;

                  meta_topic (META_DEBUG_STACK, "Placing window 0x%lx below 0x%lx\n",
                              *newp, last_window);

                  meta_stack_tracker_record_lower_below (stack->screen->stack_tracker,
                                                         *newp, last_window,
                                                         XNextRequest (stack->screen->display->xdisplay));
                  XConfigureWindow (stack->screen->display->xdisplay,
                                    *newp,
                                    CWSibling | CWStackMode,
                                    &changes);
                }

              last_window = *newp;
              ++newp;
            }
        }

      if (newp != new_end)
        {
          /* Restack remaining windows */
          meta_topic (META_DEBUG_STACK, "Restacking remaining %d windows\n",
                        (int) (new_end - newp));
          /* We need to include an already-stacked window
           * in the restack call, so we get in the proper position
           * with respect to it.
           */
          if (newp != new_stack)
            --newp;
          meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
                                                     (Window *) newp, new_end - newp,
                                                     XNextRequest (stack->screen->display->xdisplay));
          XRestackWindows (stack->screen->display->xdisplay,
                           (Window *) newp, new_end - newp);
        }
    }

  /* Push hidden windows to the bottom of the stack under the guard window */
  meta_stack_tracker_record_lower (stack->screen->stack_tracker,
                                   stack->screen->guard_window,
                                   XNextRequest (stack->screen->display->xdisplay));
  XLowerWindow (stack->screen->display->xdisplay, stack->screen->guard_window);
  meta_stack_tracker_record_restack_windows (stack->screen->stack_tracker,
                                             (Window *)all_hidden->data,
                                             all_hidden->len,
                                             XNextRequest (stack->screen->display->xdisplay));
  XRestackWindows (stack->screen->display->xdisplay,
		   (Window *)all_hidden->data,
		   all_hidden->len);
  g_array_free (all_hidden, TRUE);

  meta_error_trap_pop (stack->screen->display);
  /* on error, a window was destroyed; it should eventually
   * get removed from the stacking list when we unmanage it
   * and we'll fix stacking at that time.
   */
  
  /* Sync _NET_CLIENT_LIST and _NET_CLIENT_LIST_STACKING */

  XChangeProperty (stack->screen->display->xdisplay,
                   stack->screen->xroot,
                   stack->screen->display->atom__NET_CLIENT_LIST,
                   XA_WINDOW,
                   32, PropModeReplace,
                   (unsigned char *)stack->windows->data,
                   stack->windows->len);
  XChangeProperty (stack->screen->display->xdisplay,
                   stack->screen->xroot,
                   stack->screen->display->atom__NET_CLIENT_LIST_STACKING,
                   XA_WINDOW,
                   32, PropModeReplace,
                   (unsigned char *)stacked->data,
                   stacked->len);

  g_array_free (stacked, TRUE);

  if (stack->last_root_children_stacked)
    g_array_free (stack->last_root_children_stacked, TRUE);
  stack->last_root_children_stacked = root_children_stacked;

  /* That was scary... */
}
Пример #29
0
void
meta_window_ensure_frame (MetaWindow *window)
{
  MetaFrame *frame;
  XSetWindowAttributes attrs;
  Visual *visual;

  if (window->frame)
    return;

  /* See comment below for why this is required. */
  meta_display_grab (window->display);

  frame = g_new (MetaFrame, 1);

  frame->window = window;
  frame->xwindow = None;

  frame->rect = window->rect;
  frame->child_x = 0;
  frame->child_y = 0;
  frame->bottom_height = 0;
  frame->right_width = 0;
  frame->current_cursor = 0;

  frame->mapped = FALSE;
  frame->need_reapply_frame_shape = TRUE;
  frame->is_flashing = FALSE;

  meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
                window->desc,
                XVisualIDFromVisual (window->xvisual) ==
                XVisualIDFromVisual (window->screen->default_xvisual) ?
                "is" : "is not",
                window->depth, window->screen->default_depth);
  meta_verbose ("Frame geometry %d,%d  %dx%d\n",
                frame->rect.x, frame->rect.y,
                frame->rect.width, frame->rect.height);

  /* Default depth/visual handles clients with weird visuals; they can
   * always be children of the root depth/visual obviously, but
   * e.g. DRI games can't be children of a parent that has the same
   * visual as the client. NULL means default visual.
   *
   * We look for an ARGB visual if we can find one, otherwise use
   * the default of NULL.
   */

  /* Special case for depth 32 windows (assumed to be ARGB),
   * we use the window's visual. Otherwise we just use the system visual.
   */
  if (window->depth == 32)
    visual = window->xvisual;
  else
    visual = NULL;

  frame->xwindow = meta_ui_create_frame_window (window->screen->ui,
                                                window->display->xdisplay,
                                                visual,
                                                frame->rect.x,
                                                frame->rect.y,
						frame->rect.width,
						frame->rect.height,
						frame->window->screen->number);

  meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow);
  attrs.event_mask = EVENT_MASK;
  XChangeWindowAttributes (window->display->xdisplay,
			   frame->xwindow, CWEventMask, &attrs);

  meta_display_register_x_window (window->display, &frame->xwindow, window);

  /* Now that frame->xwindow is registered with window, we can set its
   * background.
   */
  meta_ui_reset_frame_bg (window->screen->ui, frame->xwindow);

  /* Reparent the client window; it may be destroyed,
   * thus the error trap. We'll get a destroy notify later
   * and free everything. Comment in FVWM source code says
   * we need a server grab or the child can get its MapNotify
   * before we've finished reparenting and getting the decoration
   * window onscreen, so ensure_frame must be called with
   * a grab.
   */
  meta_error_trap_push (window->display);
  if (window->mapped)
    {
      window->mapped = FALSE; /* the reparent will unmap the window,
                               * we don't want to take that as a withdraw
                               */
      meta_topic (META_DEBUG_WINDOW_STATE,
                  "Incrementing unmaps_pending on %s for reparent\n", window->desc);
      window->unmaps_pending += 1;
    }
  /* window was reparented to this position */
  window->rect.x = 0;
  window->rect.y = 0;

  XReparentWindow (window->display->xdisplay,
                   window->xwindow,
                   frame->xwindow,
                   window->rect.x,
                   window->rect.y);
  /* FIXME handle this error */
  meta_error_trap_pop (window->display, FALSE);

  /* stick frame to the window */
  window->frame = frame;

  if (window->title)
    meta_ui_set_frame_title (window->screen->ui,
                             window->frame->xwindow,
                             window->title);

  /* Move keybindings to frame instead of window */
  meta_window_grab_keys (window);

  /* Shape mask */
  meta_ui_apply_frame_shape (frame->window->screen->ui,
                             frame->xwindow,
                             frame->rect.width,
                             frame->rect.height,
                             frame->window->has_shape);
  frame->need_reapply_frame_shape = FALSE;

  meta_display_ungrab (window->display);
}
static void
mnb_panel_oop_init_panel_oop_reply_cb (DBusGProxy *proxy,
                                       gchar      *name,
                                       guint       xid,
                                       gchar      *tooltip,
                                       gchar      *stylesheet,
                                       gchar      *button_style_id,
                                       guint       window_width,
                                       guint       window_height,
                                       GError     *error,
                                       gpointer    panel)
{
  MnbPanelOopPrivate *priv = MNB_PANEL_OOP (panel)->priv;

  if (error)
    {
      g_warning ("Could not initialize Panel %s: %s",
                 mnb_panel_oop_get_name ((MnbPanel*)panel), error->message);
      g_object_unref (panel);
      return;
    }

  priv->proxy_for_owner =
    dbus_g_proxy_new_for_name_owner (priv->dbus_conn,
                                     priv->dbus_name,
                                     priv->dbus_path,
                                     MPL_PANEL_DBUS_INTERFACE,
                                     &error);

  if (error)
    {
      g_warning ("Could not create owner-specif proxy for %s: %s",
                 priv->dbus_name, error->message);
      g_clear_error (&error);
    }
  else
    {
      g_object_weak_ref (G_OBJECT (priv->proxy_for_owner),
                         mnb_panel_oop_dbus_proxy_weak_notify_cb, panel);
    }

  /*
   * We duplicate the return values, because we need to be able to replace them
   * and using the originals we would need to use dbus_malloc() later on
   * to set them afresh.
   */
  g_free (priv->name);
  priv->name = g_strdup (name);

  g_free (priv->tooltip);
  priv->tooltip = g_strdup (tooltip);

  g_free (priv->stylesheet);
  priv->stylesheet = g_strdup (stylesheet);

  g_free (priv->button_style_id);
  priv->button_style_id = g_strdup (button_style_id);

  priv->xid = xid;

  g_free (priv->child_class);

  /*
   * Retrieve the WM_CLASS property for the child window (we have to do it the
   * hard way, because the WM_CLASS on the MetaWindowActor is coming from mutter,
   * not the application).
   *
   * (We use the wm-class to identify sub-windows.)
   */
  if (xid)
    {
      Atom r_type;
      int  r_fmt;
      unsigned long n_items;
      unsigned long r_after;
      char *r_prop;
      MetaPlugin *plugin = meego_netbook_get_plugin_singleton ();
      MetaDisplay *display;

      display = meta_screen_get_display (meta_plugin_get_screen (plugin));

      meta_error_trap_push (display);

      if (Success == XGetWindowProperty (gdk_x11_display_get_xdisplay(gdk_display_get_default ()), xid, XA_WM_CLASS,
                                         0, 8192,
                                         False, XA_STRING,
                                         &r_type, &r_fmt, &n_items, &r_after,
                                         (unsigned char **)&r_prop) &&
          r_type != 0)
        {
          if (r_prop)
            {
              /*
               * The property contains two strings separated by \0; we want the
               * second string.
               */
              gint len0 = strlen (r_prop);

              if (len0 == n_items)
                len0--;

              priv->child_class = g_strdup (r_prop + len0 + 1);

              XFree (r_prop);
            }
        }

      meta_error_trap_pop (display);
    }

  priv->dead = FALSE;
  priv->initialized = TRUE;

  if (priv->ready)
    g_signal_emit (panel, signals[READY], 0);

  dbus_free (name);
  dbus_free (tooltip);
  dbus_free (stylesheet);
  dbus_free (button_style_id);
}