Пример #1
0
static gboolean
test_case_check_xserver_stacking (TestCase *test,
                                  GError  **error)
{
  MetaDisplay *display = meta_get_display ();
  GString *local_string = g_string_new (NULL);
  GString *x11_string = g_string_new (NULL);
  int i;

  guint64 *windows;
  int n_windows;
  meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows);

  for (i = 0; i < n_windows; i++)
    {
      if (META_STACK_ID_IS_X11 (windows[i]))
        {
          if (local_string->len > 0)
            g_string_append_c (local_string, ' ');

          g_string_append_printf (local_string, "%#lx", (Window)windows[i]);
        }
    }

  Window root;
  Window parent;
  Window *children;
  unsigned int n_children;
  XQueryTree (display->xdisplay,
              meta_screen_get_xroot (display->screen),
              &root, &parent, &children, &n_children);

  for (i = 0; i < (int)n_children; i++)
    {
      if (x11_string->len > 0)
        g_string_append_c (x11_string, ' ');

      g_string_append_printf (x11_string, "%#lx", (Window)children[i]);
    }

  if (strcmp (x11_string->str, local_string->str) != 0)
    g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
                 "xserver stacking: x11='%s', local='%s'",
                 x11_string->str, local_string->str);

  XFree (children);

  g_string_free (local_string, TRUE);
  g_string_free (x11_string, TRUE);

  return *error == NULL;
}
Пример #2
0
/**
 * meta_stack_tracker_sync_stack:
 * @tracker: a #MetaStackTracker
 *
 * Informs the compositor of the current stacking order of windows,
 * based on the predicted view maintained by the #MetaStackTracker.
 */
void
meta_stack_tracker_sync_stack (MetaStackTracker *tracker)
{
  GList *meta_windows;
  Window *windows;
  int n_windows;
  int i;

  if (tracker->sync_stack_later)
    {
      meta_later_remove (tracker->sync_stack_later);
      tracker->sync_stack_later = 0;
    }

  meta_stack_tracker_get_stack (tracker, &windows, &n_windows);

  meta_windows = NULL;
  for (i = 0; i < n_windows; i++)
    {
      MetaWindow *meta_window;

      meta_window = meta_display_lookup_x_window (tracker->screen->display,
                                                  windows[i]);
      /* When mapping back from xwindow to MetaWindow we have to be a bit careful;
       * children of the root could include unmapped windows created by toolkits
       * for internal purposes, including ones that we have registered in our
       * XID => window table. (Wine uses a toplevel for _NET_WM_USER_TIME_WINDOW;
       * see window-prop.c:reload_net_wm_user_time_window() for registration.)
       */
      if (meta_window &&
          (windows[i] == meta_window->xwindow ||
           (meta_window->frame && windows[i] == meta_window->frame->xwindow)))
        meta_windows = g_list_prepend (meta_windows, meta_window);
    }

  if (tracker->screen->display->compositor)
    meta_compositor_sync_stack (tracker->screen->display->compositor,
                                tracker->screen,
                                meta_windows);
  g_list_free (meta_windows);

  meta_screen_restacked (tracker->screen);
}
Пример #3
0
static gboolean
test_case_assert_stacking (TestCase *test,
                           char    **expected_windows,
                           int       n_expected_windows,
                           GError  **error)
{
  MetaDisplay *display = meta_get_display ();
  guint64 *windows;
  int n_windows;
  GString *stack_string = g_string_new (NULL);
  GString *expected_string = g_string_new (NULL);
  int i;

  meta_stack_tracker_get_stack (display->screen->stack_tracker, &windows, &n_windows);
  for (i = 0; i < n_windows; i++)
    {
      MetaWindow *window = meta_display_lookup_stack_id (display, windows[i]);
      if (window != NULL && window->title)
        {
          /* See comment in meta_ui_new() about why the dummy window for GTK+ theming
           * is managed as a MetaWindow.
           */
          if (META_STACK_ID_IS_X11 (windows[i]) &&
              meta_ui_window_is_dummy (display->screen->ui, windows[i]))
            continue;

          if (stack_string->len > 0)
            g_string_append_c (stack_string, ' ');

          if (g_str_has_prefix (window->title, "test/"))
            g_string_append (stack_string, window->title + 5);
          else
            g_string_append_printf (stack_string, "(%s)", window->title);
        }
      else if (windows[i] == display->screen->guard_window)
        {
          if (stack_string->len > 0)
            g_string_append_c (stack_string, ' ');

          g_string_append_c (stack_string, '|');
        }
    }

  for (i = 0; i < n_expected_windows; i++)
    {
      if (expected_string->len > 0)
        g_string_append_c (expected_string, ' ');

      g_string_append (expected_string, expected_windows[i]);
    }

  /* Don't require '| ' as a prefix if there are no hidden windows - we
   * remove the prefix from the actual string instead of adding it to the
   * expected string for clarity of the error message
   */
  if (index (expected_string->str, '|') == NULL && stack_string->str[0] == '|')
    {
      g_string_erase (stack_string,
                      0, stack_string->str[1] == ' ' ? 2 : 1);
    }

  if (strcmp (expected_string->str, stack_string->str) != 0)
    {
      g_set_error (error, TEST_RUNNER_ERROR, TEST_RUNNER_ERROR_ASSERTION_FAILED,
                   "stacking: expected='%s', actual='%s'",
                   expected_string->str, stack_string->str);
    }

  g_string_free (stack_string, TRUE);
  g_string_free (expected_string, TRUE);

  return *error == NULL;
}
Пример #4
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);
    }
}