コード例 #1
0
ファイル: stack.c プロジェクト: collinss/muffin
static void
stack_do_window_additions (MetaStack *stack)
{
  GList *tmp;
  gint i, n_added;

  n_added = g_list_length (stack->added);
  if (n_added > 0)
    {
      Window *end;
      int old_size;

      meta_topic (META_DEBUG_STACK,
                  "Adding %d windows to sorted list\n",
                  n_added);
      
      old_size = stack->windows->len;
      g_array_set_size (stack->windows, old_size + n_added);
      
      end = &g_array_index (stack->windows, Window, old_size);

      /* stack->added has the most recent additions at the
       * front of the list, so we need to reverse it
       */
      stack->added = g_list_reverse (stack->added);
      
      i = 0;
      tmp = stack->added;
      while (tmp != NULL)
        {
          MetaWindow *w;
          
          w = tmp->data;
          
          end[i] = w->xwindow;

          /* add to the main list */
          stack->sorted = g_list_prepend (stack->sorted, w);
          
          ++i;
          tmp = tmp->next;
        }
      
      stack->need_resort = TRUE; /* may not be needed as we add to top */
      stack->need_constrain = TRUE;
      stack->need_relayer = TRUE;
    }

  g_list_free (stack->added);
  stack->added = NULL;
}
コード例 #2
0
static void
compute_layer (MetaWindow *window)
{
  window->layer = get_standalone_layer (window);
  
  /* We can only do promotion-due-to-group for dialogs and other
   * transients, or weird stuff happens like the desktop window and
   * caja windows getting in the same layer, or all mate-terminal
   * windows getting in fullscreen layer if any terminal is
   * fullscreen.
   */
  if (WINDOW_HAS_TRANSIENT_TYPE(window) &&
      (window->xtransient_for == None ||
       window->transient_parent_is_root_window))
    {
      /* We only do the group thing if the dialog is NOT transient for
       * a particular window. Imagine a group with a normal window, a dock,
       * and a dialog transient for the normal window; you don't want the dialog
       * above the dock if it wouldn't normally be.
       */
      
      MetaStackLayer group_max;
      
      group_max = get_maximum_layer_in_group (window);
      
      if (group_max > window->layer)
        {
          meta_topic (META_DEBUG_STACK,
                      "Promoting window %s from layer %u to %u due to group membership\n",
                      window->desc, window->layer, group_max);
          window->layer = group_max;
        }
    }

  meta_topic (META_DEBUG_STACK, "Window %s on layer %u type = %u has_focus = %d\n",
              window->desc, window->layer,
              window->type, window->has_focus);
}
コード例 #3
0
ファイル: stack.c プロジェクト: mchalupa/mutter
static void
ensure_above (MetaWindow *above,
              MetaWindow *below)
{
  if (WINDOW_HAS_TRANSIENT_TYPE(above) &&
      above->layer < below->layer)
    {
      meta_topic (META_DEBUG_STACK,
		  "Promoting window %s from layer %u to %u due to contraint\n",
		  above->desc, above->layer, below->layer);
      above->layer = below->layer;
    }

  if (above->stack_position < below->stack_position)
    {
      /* move above to below->stack_position bumping below down the stack */
      meta_window_set_stack_position_no_sync (above, below->stack_position);
      g_assert (below->stack_position + 1 == above->stack_position);
    }
  meta_topic (META_DEBUG_STACK, "%s above at %d > %s below at %d\n",
              above->desc, above->stack_position,
              below->desc, below->stack_position);
}
コード例 #4
0
ファイル: stack.c プロジェクト: mchalupa/mutter
/**
 * stack_do_resort:
 *
 * Sort stack->sorted with layers having priority over stack_position.
 */
static void
stack_do_resort (MetaStack *stack)
{
  if (!stack->need_resort)
    return;

  meta_topic (META_DEBUG_STACK,
              "Sorting stack list\n");

  stack->sorted = g_list_sort (stack->sorted,
                               (GCompareFunc) compare_window_position);

  stack->need_resort = FALSE;
}
コード例 #5
0
ファイル: session.c プロジェクト: JonahAragon/consortium
static void 
interact_callback (SmcConn smc_conn, SmPointer client_data)
{
  /* nothing */
  gboolean shutdown;

  meta_topic (META_DEBUG_SM, "Interaction permission received\n");
  
  shutdown = GPOINTER_TO_INT (client_data);

  current_state = STATE_DONE_WITH_INTERACT;

  warn_about_lame_clients_and_finish_interact (shutdown);
}
コード例 #6
0
ファイル: session.c プロジェクト: JonahAragon/consortium
static void 
save_phase_2_callback (SmcConn smc_conn, SmPointer client_data)
{
  gboolean shutdown;

  meta_topic (META_DEBUG_SM, "Phase 2 save");
  
  shutdown = GPOINTER_TO_INT (client_data);
  
  current_state = STATE_SAVING_PHASE_2;

  save_state ();
  
  save_yourself_possibly_done (shutdown, TRUE);
}
コード例 #7
0
ファイル: workspace.c プロジェクト: mitya57/metacity
void
meta_workspace_add_window (MetaWorkspace *workspace,
                           MetaWindow    *window)
{
  g_return_if_fail (window->workspace == NULL);
  
  /* If the window is on all workspaces, we want to add it to all mru
   * lists, otherwise just add it to this workspaces mru list
   */
  if (window->on_all_workspaces) 
    {
      if (window->workspace == NULL)
        {
          GList* tmp = window->screen->workspaces;
          while (tmp)
            {
              MetaWorkspace* work = (MetaWorkspace*) tmp->data;
              if (!g_list_find (work->mru_list, window))
                work->mru_list = g_list_prepend (work->mru_list, window);

              tmp = tmp->next;
            }
        }
    }
  else
    {
      g_assert (g_list_find (workspace->mru_list, window) == NULL);
      workspace->mru_list = g_list_prepend (workspace->mru_list, window);
    }

  workspace->windows = g_list_prepend (workspace->windows, window);
  window->workspace = workspace;

  meta_window_set_current_workspace_hint (window);
  
  if (window->struts)
    {
      meta_topic (META_DEBUG_WORKAREA,
                  "Invalidating work area of workspace %d since we're adding window %s to it\n",
                  meta_workspace_index (workspace), window->desc);
      meta_workspace_invalidate_work_area (workspace);
    }

  /* queue a move_resize since changing workspaces may change
   * the relevant struts
   */
  meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE);
}
コード例 #8
0
void
meta_workspace_remove_window (MetaWorkspace *workspace,
                              MetaWindow    *window)
{
  g_return_if_fail (window->workspace == workspace);

  workspace->windows = g_list_remove (workspace->windows, window);
  window->workspace = NULL;

  /* If the window is on all workspaces, we don't want to remove it
   * from the MRU list unless this causes it to be removed from all 
   * workspaces
   */
  if (window->on_all_workspaces) 
    {
      GList* tmp = window->screen->workspaces;
      while (tmp)
        {
          MetaWorkspace* work = (MetaWorkspace*) tmp->data;
          work->mru_list = g_list_remove (work->mru_list, window);

          tmp = tmp->next;
        }
    }
  else
    {
      workspace->mru_list = g_list_remove (workspace->mru_list, window);
      g_assert (g_list_find (workspace->mru_list, window) == NULL);
    }

  meta_window_set_current_workspace_hint (window);
  
  if (window->struts)
    {
      meta_topic (META_DEBUG_WORKAREA,
                  "Invalidating work area of workspace %d since we're removing window %s from it\n",
                  meta_workspace_index (workspace), window->desc);
      meta_workspace_invalidate_work_area (workspace);
    }

  /* queue a move_resize since changing workspaces may change
   * the relevant struts
   */
  meta_window_queue (window, META_QUEUE_CALC_SHOWING|META_QUEUE_MOVE_RESIZE);

  g_signal_emit (workspace, signals[WINDOW_REMOVED], 0, window);
  g_object_notify (G_OBJECT (workspace), "n-windows");
}
コード例 #9
0
ファイル: group.c プロジェクト: endlessm/mutter
static void
remove_window_from_group (MetaWindow *window)
{
  if (window->group != NULL)
    {
      meta_topic (META_DEBUG_GROUPS,
                  "Removing %s from group with leader 0x%lx\n",
                  window->desc, window->group->group_leader);

      window->group->windows =
        g_slist_remove (window->group->windows,
                        window);
      meta_group_unref (window->group);
      window->group = NULL;
    }
}
コード例 #10
0
ファイル: delete.c プロジェクト: FrodeSolheim/marco
static void
delete_ping_timeout_func (MetaDisplay *display,
                          Window       xwindow,
                          guint32      timestamp,
                          void        *user_data)
{
  MetaWindow *window = user_data;
  char *window_title;
  gchar *window_content, *tmp;
  GPid dialog_pid;

  meta_topic (META_DEBUG_PING,
              "Got delete ping timeout for %s\n",
              window->desc);

  if (window->dialog_pid >= 0)
    {
      meta_window_present_delete_dialog (window, timestamp);
      return;
    }

  window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);

  /* Translators: %s is a window title */
  tmp = g_strdup_printf (_("<tt>%s</tt> is not responding."),
                         window_title);
  window_content = g_strdup_printf (
      "<big><b>%s</b></big>\n\n<i>%s</i>",
      tmp,
      _("You may choose to wait a short while for it to "
        "continue or force the application to quit entirely."));

  g_free (window_title);

  dialog_pid =
    meta_show_dialog ("--question",
                      window_content, 0,
                      window->screen->number,
                      _("_Wait"), _("_Force Quit"), window->xwindow,
                      NULL, NULL);

  g_free (window_content);
  g_free (tmp);

  window->dialog_pid = dialog_pid;
  g_child_watch_add (dialog_pid, dialog_exited, window);
}
コード例 #11
0
static void
delete_ping_timeout_func (MetaDisplay *display,
                          Window       xwindow,
                          guint32      timestamp,
                          void        *user_data)
{
  MetaWindow *window = user_data;
  char *window_title;
  gchar *window_content;
  GPid dialog_pid;
  
  meta_topic (META_DEBUG_PING,
              "Got delete ping timeout for %s\n",
              window->desc);

  if (window->dialog_pid >= 0)
    {
      meta_window_present_delete_dialog (window, timestamp);
      return;
    }

  window_title = g_locale_from_utf8 (window->title, -1, NULL, NULL, NULL);

  window_content = g_strdup_printf(
      _("<big><b><tt>%s</tt> is not responding.</b></big>\n\n"
      "<i>You may choose to wait a short while for it to "
      "continue or force the application to quit entirely.</i>"),
      window_title);

  g_free (window_title);

  dialog_pid =
    meta_show_dialog ("--question",
                      window_content, 0,
                      window->screen->number,
                      _("_Wait"), _("_Force Quit"), window->xwindow,
                      NULL, NULL);

  g_free (window_content);

  window->dialog_pid = dialog_pid;

  g_signal_connect (sigchld_nexus, "sigchld",
                    G_CALLBACK (sigchld_handler),
                    window);

}
コード例 #12
0
ファイル: errors.c プロジェクト: BrotherAl/marco
void
meta_error_trap_pop (MetaDisplay *display,
                     gboolean     last_request_was_roundtrip)
{
  gboolean need_sync;

  /* we only have to sync when popping the outermost trap */
  need_sync = (display->error_traps == 1 && !last_request_was_roundtrip);

  if (need_sync)
    meta_topic (META_DEBUG_SYNC, "Syncing on error_trap_pop, traps = %d, roundtrip = %d\n",
                display->error_traps, last_request_was_roundtrip);

  display->error_trap_synced_at_last_pop = need_sync || last_request_was_roundtrip;

  meta_error_trap_pop_internal (display, need_sync);
}
コード例 #13
0
ファイル: frame.c プロジェクト: Big1av/muffin
LOCAL_SYMBOL gboolean
meta_frame_sync_to_window (MetaFrame *frame,
                           int        resize_gravity,
                           gboolean   need_move,
                           gboolean   need_resize)
{
  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)
    {
      meta_ui_unflicker_frame_bg (frame->window->screen->ui,
                                  frame->xwindow,
                                  frame->rect.width,
                                  frame->rect.height);
    }

  meta_ui_move_resize_frame (frame->window->screen->ui,
			     frame->xwindow,
			     frame->rect.x,
			     frame->rect.y,
			     frame->rect.width,
			     frame->rect.height);

  if (need_resize)
    {
      meta_ui_reset_frame_bg (frame->window->screen->ui,
                              frame->xwindow);

      /* 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;
}
コード例 #14
0
gboolean
meta_frame_sync_to_window (MetaFrame *frame,
                           gboolean   need_resize)
{
  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);

  meta_ui_frame_move_resize (frame->ui_frame,
			     frame->rect.x,
			     frame->rect.y,
			     frame->rect.width,
			     frame->rect.height);

  return need_resize;
}
コード例 #15
0
static MetaGroup*
meta_group_new (MetaDisplay *display,
                Window       group_leader)
{
  MetaGroup *group;
#define N_INITIAL_PROPS 3
  Atom initial_props[N_INITIAL_PROPS];
  int i;
  
  g_assert (N_INITIAL_PROPS == (int) G_N_ELEMENTS (initial_props));
  
  group = g_new0 (MetaGroup, 1);

  group->display = display;
  group->windows = NULL;
  group->group_leader = group_leader;
  group->refcount = 1; /* owned by caller, hash table has only weak ref */
  
  if (display->groups_by_leader == NULL)
    display->groups_by_leader = g_hash_table_new (meta_unsigned_long_hash,
                                                  meta_unsigned_long_equal);

  g_assert (g_hash_table_lookup (display->groups_by_leader, &group_leader) == NULL);

  g_hash_table_insert (display->groups_by_leader,
                       &group->group_leader,
                       group);

  /* Fill these in the order we want them to be gotten */
  i = 0;
  initial_props[i++] = display->atom_WM_CLIENT_MACHINE;
  initial_props[i++] = display->atom__NET_WM_PID;
  initial_props[i++] = display->atom__NET_STARTUP_ID;
  g_assert (N_INITIAL_PROPS == i);
  
  meta_group_reload_properties (group, initial_props, N_INITIAL_PROPS);

  meta_topic (META_DEBUG_GROUPS,
              "Created new group with leader 0x%lx\n",
              group->group_leader);
  
  return group;
}
コード例 #16
0
static void
avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
                                             MetaFrameGeometry *fgeom,
                                             int        *x,
                                             int        *y)
{
  /* We can't center this dialog if it was denied focus and it
   * overlaps with the focus window and this dialog is modal and this
   * dialog is in the same app as the focus window (*phew*...please
   * don't make me say that ten times fast). See bug 307875 comment 11
   * and 12 for details, but basically it means this is probably a
   * second modal dialog for some app while the focus window is the
   * first modal dialog.  We should probably make them simultaneously
   * visible in general, but it becomes mandatory to do so due to
   * buggy apps (e.g. those using gtk+ *sigh*) because in those cases
   * this second modal dialog also happens to be modal to the first
   * dialog in addition to the main window, while it has only let us
   * know about the modal-to-the-main-window part.
   */

  MetaWindow *focus_window;
  MetaRectangle overlap;

  focus_window = window->display->focus_window;

  if (window->denied_focus_and_not_transient &&
      window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
      meta_window_same_application (window, focus_window) &&
      meta_rectangle_intersect (&window->rect,
                                &focus_window->rect,
                                &overlap))
    {
      find_most_freespace (window, fgeom, focus_window, *x, *y, x, y);
      meta_topic (META_DEBUG_PLACEMENT,
                  "Dialog window %s was denied focus but may be modal "
                  "to the focus window; had to move it to avoid the "
                  "focus window\n",
                  window->desc);
    }
}
コード例 #17
0
ファイル: stack.c プロジェクト: mchalupa/mutter
void
meta_stack_set_positions (MetaStack *stack,
                          GList     *windows)
{
  int i;
  GList *tmp;

  /* Make sure any adds or removes aren't in limbo -- is this needed? */
  stack_ensure_sorted (stack);

  if (!lists_contain_same_windows (windows, stack->sorted))
    {
      meta_warning ("This list of windows has somehow changed; not resetting "
                    "positions of the windows.\n");
      return;
    }

  g_list_free (stack->sorted);
  stack->sorted = g_list_copy (windows);

  stack->need_resort = TRUE;
  stack->need_constrain = TRUE;

  i = 0;
  tmp = windows;
  while (tmp != NULL)
    {
      MetaWindow *w = tmp->data;
      w->stack_position = i++;
      tmp = tmp->next;
    }

  meta_topic (META_DEBUG_STACK,
              "Reset the stack positions of (nearly) all windows\n");

  stack_sync_to_xserver (stack);
  meta_stack_update_window_tile_matches (stack, NULL);
}
コード例 #18
0
ファイル: prefs.c プロジェクト: JazzGirl/metacity
const char*
meta_prefs_get_workspace_name (int i)
{
    const char *name;

    g_return_val_if_fail (i >= 0, NULL);

    if (!workspace_names ||
            g_strv_length (workspace_names) < (guint)i + 1 ||
            !*workspace_names[i])
    {
        char *generated_name = g_strdup_printf (_("Workspace %d"), i + 1);
        name = g_intern_string (generated_name);
        g_free (generated_name);
    }
    else
        name = workspace_names[i];

    meta_topic (META_DEBUG_PREFS,
                "Getting name of workspace %d: \"%s\"\n", i, name);

    return name;
}
コード例 #19
0
ファイル: main.c プロジェクト: mitya57/metacity
/**
 * Prints a list of which configure script options were used to
 * build this copy of Metacity. This is actually always called
 * on startup, but it's all no-op unless we're in verbose mode
 * (see meta_set_verbose).
 */
static void
meta_print_compilation_info (void)
{
#ifdef HAVE_SHAPE
  meta_verbose ("Compiled with shape extension\n");
#else
  meta_verbose ("Compiled without shape extension\n");
#endif
#ifdef HAVE_XINERAMA
  meta_topic (META_DEBUG_XINERAMA, "Compiled with Xinerama extension\n");
#else
  meta_topic (META_DEBUG_XINERAMA, "Compiled without Xinerama extension\n");
#endif
#ifdef HAVE_XFREE_XINERAMA
  meta_topic (META_DEBUG_XINERAMA, " (using XFree86 Xinerama)\n");
#else
  meta_topic (META_DEBUG_XINERAMA, " (not using XFree86 Xinerama)\n");
#endif
#ifdef HAVE_SOLARIS_XINERAMA
  meta_topic (META_DEBUG_XINERAMA, " (using Solaris Xinerama)\n");
#else
  meta_topic (META_DEBUG_XINERAMA, " (not using Solaris Xinerama)\n");
#endif
#ifdef HAVE_XSYNC
  meta_verbose ("Compiled with sync extension\n");
#else
  meta_verbose ("Compiled without sync extension\n");
#endif
#ifdef HAVE_RANDR
  meta_verbose ("Compiled with randr extension\n");
#else
  meta_verbose ("Compiled without randr extension\n");
#endif
#ifdef HAVE_STARTUP_NOTIFICATION
  meta_verbose ("Compiled with startup notification\n");
#else
  meta_verbose ("Compiled without startup notification\n");
#endif
#ifdef HAVE_COMPOSITE_EXTENSIONS
  meta_verbose ("Compiled with composite extensions\n");
#else
  meta_verbose ("Compiled without composite extensions\n");
#endif
}
コード例 #20
0
ファイル: prefs.c プロジェクト: JazzGirl/metacity
static void
emit_changed (MetaPreference pref)
{
    GList *tmp;
    GList *copy;

    meta_topic (META_DEBUG_PREFS, "Notifying listeners that pref %s changed\n",
                meta_preference_to_string (pref));

    copy = g_list_copy (listeners);

    tmp = copy;

    while (tmp != NULL)
    {
        MetaPrefsListener *l = tmp->data;

        (* l->func) (pref, l->data);

        tmp = tmp->next;
    }

    g_list_free (copy);
}
コード例 #21
0
static void
meta_window_present_delete_dialog (MetaWindow *window, guint32 timestamp)
{
  meta_topic (META_DEBUG_PING,
              "Presenting existing ping dialog for %s\n",
              window->desc);
  
  if (window->dialog_pid >= 0)
    {
      GSList *windows;
      GSList *tmp;

      /* Activate transient for window that belongs to
       * metacity-dialog
       */
      
      windows = meta_display_list_windows (window->display);
      tmp = windows;
      while (tmp != NULL)
        {
          MetaWindow *w = tmp->data;

          if (w->xtransient_for == window->xwindow &&
              w->res_class &&
              g_ascii_strcasecmp (w->res_class, "metacity-dialog") == 0)
            {
              meta_window_activate (w, timestamp);
              break;
            }
          
          tmp = tmp->next;
        }

      g_slist_free (windows);
    }
}
コード例 #22
0
ファイル: stack.c プロジェクト: mchalupa/mutter
static void
create_constraints (Constraint **constraints,
                    GList       *windows)
{
  GList *tmp;

  tmp = windows;
  while (tmp != NULL)
    {
      MetaWindow *w = tmp->data;

      if (!WINDOW_IN_STACK (w))
        {
          meta_topic (META_DEBUG_STACK, "Window %s not in the stack, not constraining it\n",
                      w->desc);
          tmp = tmp->next;
          continue;
        }

      if (WINDOW_TRANSIENT_FOR_WHOLE_GROUP (w))
        {
          GSList *group_windows;
          GSList *tmp2;
          MetaGroup *group;

          group = meta_window_get_group (w);

          if (group != NULL)
            group_windows = meta_group_list_windows (group);
          else
            group_windows = NULL;

          tmp2 = group_windows;

          while (tmp2 != NULL)
            {
              MetaWindow *group_window = tmp2->data;

              if (!WINDOW_IN_STACK (group_window) ||
                  w->screen != group_window->screen ||
                  group_window->override_redirect)
                {
                  tmp2 = tmp2->next;
                  continue;
                }

#if 0
              /* old way of doing it */
              if (!(meta_window_is_ancestor_of_transient (w, group_window)) &&
                  !WINDOW_TRANSIENT_FOR_WHOLE_GROUP (group_window))  /* note */;/*note*/
#else
              /* better way I think, so transient-for-group are constrained
               * only above non-transient-type windows in their group
               */
              if (!WINDOW_HAS_TRANSIENT_TYPE (group_window))
#endif
                {
                  meta_topic (META_DEBUG_STACK, "Constraining %s above %s as it's transient for its group\n",
                              w->desc, group_window->desc);
                  add_constraint (constraints, w, group_window);
                }

              tmp2 = tmp2->next;
            }

          g_slist_free (group_windows);
        }
      else if (w->transient_for != NULL)
        {
          MetaWindow *parent;

          parent = w->transient_for;

          if (parent && WINDOW_IN_STACK (parent))
            {
              meta_topic (META_DEBUG_STACK, "Constraining %s above %s due to transiency\n",
                          w->desc, parent->desc);
              add_constraint (constraints, w, parent);
            }
        }

      tmp = tmp->next;
    }
}
コード例 #23
0
static void
ensure_work_areas_validated (MetaWorkspace *workspace)
{
  GList         *windows;
  GList         *tmp;
  MetaRectangle  work_area;
  int            i;  /* C89 absolutely sucks... */

  if (!workspace->work_areas_invalid)
    return;

  g_assert (workspace->all_struts == NULL);
  g_assert (workspace->monitor_region == NULL);
  g_assert (workspace->screen_region == NULL);
  g_assert (workspace->screen_edges == NULL);
  g_assert (workspace->monitor_edges == NULL);

  /* STEP 1: Get the list of struts */

  workspace->all_struts = copy_strut_list (workspace->builtin_struts);

  windows = meta_workspace_list_windows (workspace);
  for (tmp = windows; tmp != NULL; tmp = tmp->next)
    {
      MetaWindow *win = tmp->data;
      GSList *s_iter;

      for (s_iter = win->struts; s_iter != NULL; s_iter = s_iter->next) {
        workspace->all_struts = g_slist_prepend (workspace->all_struts,
                                                 copy_strut(s_iter->data));
      }
    }
  g_list_free (windows);

  /* STEP 2: Get the maximal/spanning rects for the onscreen and
   *         on-single-monitor regions
   */  
  g_assert (workspace->monitor_region == NULL);
  g_assert (workspace->screen_region   == NULL);

  workspace->monitor_region = g_new (GList*,
                                      workspace->screen->n_monitor_infos);
  for (i = 0; i < workspace->screen->n_monitor_infos; i++)
    {
      workspace->monitor_region[i] =
        meta_rectangle_get_minimal_spanning_set_for_region (
          &workspace->screen->monitor_infos[i].rect,
          workspace->all_struts);
    }
  workspace->screen_region =
    meta_rectangle_get_minimal_spanning_set_for_region (
      &workspace->screen->rect,
      workspace->all_struts);

  /* STEP 3: Get the work areas (region-to-maximize-to) for the screen and
   *         monitors.
   */
  work_area = workspace->screen->rect;  /* start with the screen */
  if (workspace->screen_region == NULL)
    work_area = meta_rect (0, 0, -1, -1);
  else
    meta_rectangle_clip_to_region (workspace->screen_region,
                                   FIXED_DIRECTION_NONE,
                                   &work_area);

  /* Lots of paranoia checks, forcing work_area_screen to be sane */
#define MIN_SANE_AREA 100
  if (work_area.width < MIN_SANE_AREA)
    {
      meta_warning ("struts occupy an unusually large percentage of the screen; "
                    "available remaining width = %d < %d",
                    work_area.width, MIN_SANE_AREA);
      if (work_area.width < 1)
        {
          work_area.x = (workspace->screen->rect.width - MIN_SANE_AREA)/2;
          work_area.width = MIN_SANE_AREA;
        }
      else
        {
          int amount = (MIN_SANE_AREA - work_area.width)/2;
          work_area.x     -=   amount;
          work_area.width += 2*amount;
        }
    }
  if (work_area.height < MIN_SANE_AREA)
    {
      meta_warning ("struts occupy an unusually large percentage of the screen; "
                    "available remaining height = %d < %d",
                    work_area.height, MIN_SANE_AREA);
      if (work_area.height < 1)
        {
          work_area.y = (workspace->screen->rect.height - MIN_SANE_AREA)/2;
          work_area.height = MIN_SANE_AREA;
        }
      else
        {
          int amount = (MIN_SANE_AREA - work_area.height)/2;
          work_area.y      -=   amount;
          work_area.height += 2*amount;
        }
    }
  workspace->work_area_screen = work_area;
  meta_topic (META_DEBUG_WORKAREA,
              "Computed work area for workspace %d: %d,%d %d x %d\n",
              meta_workspace_index (workspace),
              workspace->work_area_screen.x,
              workspace->work_area_screen.y,
              workspace->work_area_screen.width,
              workspace->work_area_screen.height);    

  /* Now find the work areas for each monitor */
  g_free (workspace->work_area_monitor);
  workspace->work_area_monitor = g_new (MetaRectangle,
                                         workspace->screen->n_monitor_infos);

  for (i = 0; i < workspace->screen->n_monitor_infos; i++)
    {
      work_area = workspace->screen->monitor_infos[i].rect;

      if (workspace->monitor_region[i] == NULL)
        /* FIXME: constraints.c untested with this, but it might be nice for
         * a screen reader or magnifier.
         */
        work_area = meta_rect (work_area.x, work_area.y, -1, -1);
      else
        meta_rectangle_clip_to_region (workspace->monitor_region[i],
                                       FIXED_DIRECTION_NONE,
                                       &work_area);

      workspace->work_area_monitor[i] = work_area;
      meta_topic (META_DEBUG_WORKAREA,
                  "Computed work area for workspace %d "
                  "monitor %d: %d,%d %d x %d\n",
                  meta_workspace_index (workspace),
                  i,
                  workspace->work_area_monitor[i].x,
                  workspace->work_area_monitor[i].y,
                  workspace->work_area_monitor[i].width,
                  workspace->work_area_monitor[i].height);
    }

  /* STEP 4: Make sure the screen_region is nonempty (separate from step 2
   *         since it relies on step 3).
   */  
  if (workspace->screen_region == NULL)
    {
      MetaRectangle *nonempty_region;
      nonempty_region = g_new (MetaRectangle, 1);
      *nonempty_region = workspace->work_area_screen;
      workspace->screen_region = g_list_prepend (NULL, nonempty_region);
    }

  /* STEP 5: Cache screen and monitor edges for edge resistance and snapping */
  g_assert (workspace->screen_edges    == NULL);
  g_assert (workspace->monitor_edges  == NULL);
  workspace->screen_edges =
    meta_rectangle_find_onscreen_edges (&workspace->screen->rect,
                                        workspace->all_struts);
  tmp = NULL;
  for (i = 0; i < workspace->screen->n_monitor_infos; i++)
    tmp = g_list_prepend (tmp, &workspace->screen->monitor_infos[i].rect);
  workspace->monitor_edges =
    meta_rectangle_find_nonintersected_monitor_edges (tmp,
                                                       workspace->all_struts);
  g_list_free (tmp);

  /* We're all done, YAAY!  Record that everything has been validated. */
  workspace->work_areas_invalid = FALSE;

  {
    /*
     * Notify the compositor that the workspace geometry has changed.
     */
    MetaScreen     *screen = workspace->screen;
    MetaDisplay    *display = meta_screen_get_display (screen);
    MetaCompositor *comp = meta_display_get_compositor (display);

    if (comp)
      meta_compositor_update_workspace_geometry (comp, workspace);
  }
}
コード例 #24
0
/**
 * meta_workspace_activate_with_focus:
 * @workspace: a #MetaWorkspace
 * @focus_this: the #MetaWindow to be focused, or %NULL
 * @timestamp: timestamp for @focus_this
 *
 * Switches to @workspace and possibly activates the window @focus_this.
 *
 * The window @focus_this is activated by calling meta_window_activate()
 * which will unminimize it and transient parents, raise it and give it
 * the focus.
 *
 * If a window is currently being moved by the user, it will be
 * moved to @workspace.
 *
 * The advantage of calling this function instead of meta_workspace_activate()
 * followed by meta_window_activate() is that it happens as a unit, so
 * no other window gets focused first before @focus_this.
 */
void
meta_workspace_activate_with_focus (MetaWorkspace *workspace,
                                    MetaWindow    *focus_this,
                                    guint32        timestamp)
{
  MetaWorkspace  *old;
  MetaWindow     *move_window;
  MetaScreen     *screen;
  MetaDisplay    *display;
  MetaCompositor *comp;
  MetaWorkspaceLayout layout1, layout2;
  gint num_workspaces, current_space, new_space;
  MetaMotionDirection direction;
  
  meta_verbose ("Activating workspace %d\n",
                meta_workspace_index (workspace));
  
  if (workspace->screen->active_workspace == workspace)
    return;

  /* Free any cached pointers to the workspaces's edges from
   * a current resize or move operation */
  meta_display_cleanup_edges (workspace->screen->display);

  if (workspace->screen->active_workspace)
    workspace_switch_sound (workspace->screen->active_workspace, workspace);

  /* Note that old can be NULL; e.g. when starting up */
  old = workspace->screen->active_workspace;

  workspace->screen->active_workspace = workspace;

  meta_screen_set_active_workspace_hint (workspace->screen);

  /* If the "show desktop" mode is active for either the old workspace
   * or the new one *but not both*, then update the
   * _net_showing_desktop hint
   */
  if (old && (old->showing_desktop ^ workspace->showing_desktop))
    meta_screen_update_showing_desktop_hint (workspace->screen);

  if (old == NULL)
    return;

  move_window = NULL;
  if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING ||
      workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
    move_window = workspace->screen->display->grab_window;
      
  if (move_window != NULL)
    {
      if (move_window->on_all_workspaces)
        move_window = NULL; /* don't move it after all */

      /* We put the window on the new workspace, flip spaces,
       * then remove from old workspace, so the window
       * never gets unmapped and we maintain the button grab
       * on it.
       *
       * \bug  This comment appears to be the reverse of what happens
       */
      if (move_window && (move_window->workspace != workspace))
        {
          meta_workspace_remove_window (old, move_window);
          meta_workspace_add_window (workspace, move_window);
        }
    }

  meta_workspace_queue_calc_showing (old);
  meta_workspace_queue_calc_showing (workspace);

  /* FIXME: Why do we need this?!?  Isn't it handled in the lines above? */
  if (move_window)
      /* Removes window from other spaces */
      meta_window_change_workspace (move_window, workspace);

   /*
    * Notify the compositor that the active workspace is changing.
    */
   screen = workspace->screen;
   display = meta_screen_get_display (screen);
   comp = meta_display_get_compositor (display);
   direction = 0;

   current_space = meta_workspace_index (old);
   new_space     = meta_workspace_index (workspace);
   num_workspaces = meta_screen_get_n_workspaces (workspace->screen);
   meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
                                      current_space, &layout1);

   meta_screen_calc_workspace_layout (workspace->screen, num_workspaces,
                                      new_space, &layout2);

   if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
     {
       if (layout1.current_col > layout2.current_col)
         direction = META_MOTION_RIGHT;
       else if (layout1.current_col < layout2.current_col)
         direction = META_MOTION_LEFT;
     }
   else
    {
       if (layout1.current_col < layout2.current_col)
         direction = META_MOTION_RIGHT;
       else if (layout1.current_col > layout2.current_col)
         direction = META_MOTION_LEFT;
    }

   if (layout1.current_row < layout2.current_row)
     {
       if (!direction)
         direction = META_MOTION_DOWN;
       else if (direction == META_MOTION_RIGHT)
         direction = META_MOTION_DOWN_RIGHT;
       else
         direction = META_MOTION_DOWN_LEFT;
     }

   if (layout1.current_row > layout2.current_row)
     {
       if (!direction)
         direction = META_MOTION_UP;
       else if (direction == META_MOTION_RIGHT)
         direction = META_MOTION_UP_RIGHT;
       else
         direction = META_MOTION_UP_LEFT;
     }

   meta_screen_free_workspace_layout (&layout1);
   meta_screen_free_workspace_layout (&layout2);

   meta_compositor_switch_workspace (comp, screen, old, workspace, direction);

  /* This needs to be done after telling the compositor we are switching
   * workspaces since focusing a window will cause it to be immediately
   * shown and that would confuse the compositor if it didn't know we
   * were in a workspace switch.
   */
  if (focus_this)
    {
      meta_window_activate (focus_this, timestamp);
    }
  else if (move_window)
    {
      meta_window_raise (move_window);
    }
  else
    {
      meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
      meta_workspace_focus_default_window (workspace, NULL, timestamp);
    }

   /* Emit switched signal from screen.c */
   meta_screen_workspace_switched (screen, current_space, new_space, direction);
}
コード例 #25
0
/* Focus ancestor of not_this_one if there is one */
static void
focus_ancestor_or_top_window (MetaWorkspace *workspace,
                              MetaWindow    *not_this_one,
                              guint32        timestamp)
{
  MetaWindow *window = NULL;

  if (not_this_one)
    meta_topic (META_DEBUG_FOCUS,
                "Focusing MRU window excluding %s\n", not_this_one->desc);
  else
    meta_topic (META_DEBUG_FOCUS,
                "Focusing MRU window\n");

  /* First, check to see if we need to focus an ancestor of a window */  
  if (not_this_one)
    {
      MetaWindow *ancestor;
      ancestor = NULL;
      meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
      if (ancestor != NULL &&
          (ancestor->on_all_workspaces ||
           ancestor->workspace == workspace) &&
          meta_window_showing_on_its_workspace (ancestor))
        {
          meta_topic (META_DEBUG_FOCUS,
                      "Focusing %s, ancestor of %s\n", 
                      ancestor->desc, not_this_one->desc);
      
          meta_window_focus (ancestor, timestamp);

          /* Also raise the window if in click-to-focus */
          if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
            meta_window_raise (ancestor);

          return;
        }
    }

  window = meta_stack_get_default_focus_window (workspace->screen->stack,
                                                workspace,
                                                NULL);

  if (window)
    {
      meta_topic (META_DEBUG_FOCUS,
                  "Focusing workspace MRU window %s\n", window->desc);
      
      meta_window_focus (window, timestamp);

      /* Also raise the window if in click-to-focus */
      if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
        meta_window_raise (window);
    }
  else
    {
      meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n");
      meta_display_focus_the_no_focus_window (workspace->screen->display,
                                              workspace->screen,
                                              timestamp);
    }
}
コード例 #26
0
void
meta_workspace_focus_default_window (MetaWorkspace *workspace,
                                     MetaWindow    *not_this_one,
                                     guint32        timestamp)
{
  if (timestamp == CurrentTime)
    {
      meta_warning ("CurrentTime used to choose focus window; "
                    "focus window may not be correct.\n");
    }


  if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK ||
      !workspace->screen->display->mouse_mode)
    focus_ancestor_or_top_window (workspace, not_this_one, timestamp);
  else
    {
      MetaWindow * window;
      window = meta_screen_get_mouse_window (workspace->screen, not_this_one);
      if (window &&
          window->type != META_WINDOW_DOCK &&
          window->type != META_WINDOW_DESKTOP)
        {
          if (timestamp == CurrentTime)
            {

              /* We would like for this to never happen.  However, if
               * it does happen then we kludge since using CurrentTime
               * can mean ugly race conditions--and we can avoid these
               * by allowing EnterNotify events (which come with
               * timestamps) to handle focus.
               */

              meta_topic (META_DEBUG_FOCUS,
                          "Not focusing mouse window %s because EnterNotify events should handle that\n", window->desc);
            }
          else
            {
              meta_topic (META_DEBUG_FOCUS,
                          "Focusing mouse window %s\n", window->desc);
              meta_window_focus (window, timestamp);
            }

          if (workspace->screen->display->autoraise_window != window &&
              meta_prefs_get_auto_raise ()) 
            {
              meta_display_queue_autoraise_callback (workspace->screen->display,
                                                     window);
            }
        }
      else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_SLOPPY)
        focus_ancestor_or_top_window (workspace, not_this_one, timestamp);
      else if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_MOUSE)
        {
          meta_topic (META_DEBUG_FOCUS,
                      "Setting focus to no_focus_window, since no valid "
                      "window to focus found.\n");
          meta_display_focus_the_no_focus_window (workspace->screen->display,
                                                  workspace->screen,
                                                  timestamp);
        }
    }
}
コード例 #27
0
ファイル: workspace.c プロジェクト: mitya57/metacity
/* Focus ancestor of not_this_one if there is one, otherwise focus the MRU
 * window on active workspace
 */
static void
focus_ancestor_or_mru_window (MetaWorkspace *workspace,
                              MetaWindow    *not_this_one,
                              guint32        timestamp)
{
  MetaWindow *window = NULL;
  MetaWindow *desktop_window = NULL;
  GList *tmp;

  if (not_this_one)
    meta_topic (META_DEBUG_FOCUS,
                "Focusing MRU window excluding %s\n", not_this_one->desc);
  else
    meta_topic (META_DEBUG_FOCUS,
                "Focusing MRU window\n");

  /* First, check to see if we need to focus an ancestor of a window */  
  if (not_this_one)
    {
      MetaWindow *ancestor;
      ancestor = NULL;
      meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor);
      if (ancestor != NULL)
        {
          meta_topic (META_DEBUG_FOCUS,
                      "Focusing %s, ancestor of %s\n", 
                      ancestor->desc, not_this_one->desc);
      
          meta_window_focus (ancestor, timestamp);

          /* Also raise the window if in click-to-focus */
          if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
            meta_window_raise (ancestor);

          return;
        }
    }

  /* No ancestor, look for the MRU window */
  tmp = workspace->mru_list;  

  while (tmp)
    {
      MetaWindow* tmp_window;
      tmp_window = ((MetaWindow*) tmp->data);
      if (tmp_window != not_this_one           &&
          meta_window_showing_on_its_workspace (tmp_window) &&
          tmp_window->type != META_WINDOW_DOCK &&
          tmp_window->type != META_WINDOW_DESKTOP)
        {
          window = tmp->data;
          break;
        }
      else if (tmp_window != not_this_one      &&
               desktop_window == NULL          &&
               meta_window_showing_on_its_workspace (tmp_window) &&
               tmp_window->type == META_WINDOW_DESKTOP)
        {
          /* Found the most recently used desktop window */
          desktop_window = tmp_window;
        }

      tmp = tmp->next;
    }

  /* If no window was found, default to the MRU desktop-window */
  if (window == NULL)
    window = desktop_window;

  if (window)
    {
      meta_topic (META_DEBUG_FOCUS,
                  "Focusing workspace MRU window %s\n", window->desc);
      
      meta_window_focus (window, timestamp);

      /* Also raise the window if in click-to-focus */
      if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK)
        meta_window_raise (window);
    }
  else
    {
      meta_topic (META_DEBUG_FOCUS, "No MRU window to focus found; focusing no_focus_window.\n");
      meta_display_focus_the_no_focus_window (workspace->screen->display,
                                              workspace->screen,
                                              timestamp);
    }
}
コード例 #28
0
ファイル: workspace.c プロジェクト: mitya57/metacity
void
meta_workspace_activate_with_focus (MetaWorkspace *workspace,
                                    MetaWindow    *focus_this,
                                    guint32        timestamp)
{
  MetaWorkspace *old;
  MetaWindow *move_window;
  
  meta_verbose ("Activating workspace %d\n",
                meta_workspace_index (workspace));
  
  if (workspace->screen->active_workspace == workspace)
    return;

  if (workspace->screen->active_workspace)
    workspace_switch_sound(workspace->screen->active_workspace, workspace);

  /* Note that old can be NULL; e.g. when starting up */
  old = workspace->screen->active_workspace;
  
  workspace->screen->active_workspace = workspace;

  set_active_space_hint (workspace->screen);

  /* If the "show desktop" mode is active for either the old workspace
   * or the new one *but not both*, then update the
   * _net_showing_desktop hint
   */
  if (old && (old->showing_desktop ^ workspace->showing_desktop))
    meta_screen_update_showing_desktop_hint (workspace->screen);

  if (old == NULL)
    return;

  move_window = NULL;
  if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING ||
      workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
    move_window = workspace->screen->display->grab_window;
      
  if (move_window != NULL)
    {
      if (move_window->on_all_workspaces)
        move_window = NULL; /* don't move it after all */

      /* We put the window on the new workspace, flip spaces,
       * then remove from old workspace, so the window
       * never gets unmapped and we maintain the button grab
       * on it.
       *
       * \bug  This comment appears to be the reverse of what happens
       */
      if (move_window && (move_window->workspace != workspace))
        {
          meta_workspace_remove_window (old, move_window);
          meta_workspace_add_window (workspace, move_window);
        }
    }

  meta_workspace_queue_calc_showing (old);
  meta_workspace_queue_calc_showing (workspace);

  /* FIXME: Why do we need this?!?  Isn't it handled in the lines above? */
  if (move_window)
      /* Removes window from other spaces */
      meta_window_change_workspace (move_window, workspace);

  if (focus_this)
    {
      meta_window_focus (focus_this, timestamp);
      meta_window_raise (focus_this);
    }
  else if (move_window)
    {
      meta_window_raise (move_window);
    }
  else
    {
      meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
      meta_workspace_focus_default_window (workspace, NULL, timestamp);
    }
}
コード例 #29
0
ファイル: place.c プロジェクト: kelsieflynn/mutter
void
meta_window_place (MetaWindow        *window,
                   int                x,
                   int                y,
                   int               *new_x,
                   int               *new_y)
{
  GList *windows = NULL;
  const MetaMonitorInfo *xi;

  meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);

  switch (window->type)
    {
      /* Run placement algorithm on these. */
    case META_WINDOW_NORMAL:
    case META_WINDOW_DIALOG:
    case META_WINDOW_MODAL_DIALOG:
    case META_WINDOW_SPLASHSCREEN:
      break;

      /* Assume the app knows best how to place these, no placement
       * algorithm ever (other than "leave them as-is")
       */
    case META_WINDOW_DESKTOP:
    case META_WINDOW_DOCK:
    case META_WINDOW_TOOLBAR:
    case META_WINDOW_MENU:
    case META_WINDOW_UTILITY:
    /* override redirect window types: */
    case META_WINDOW_DROPDOWN_MENU:
    case META_WINDOW_POPUP_MENU:
    case META_WINDOW_TOOLTIP:
    case META_WINDOW_NOTIFICATION:
    case META_WINDOW_COMBO:
    case META_WINDOW_DND:
    case META_WINDOW_OVERRIDE_OTHER:
      goto done;
    }

  if (meta_prefs_get_disable_workarounds ())
    {
      switch (window->type)
        {
          /* Only accept USPosition on normal windows because the app is full
           * of shit claiming the user set -geometry for a dialog or dock
           */
        case META_WINDOW_NORMAL:
          if (window->size_hints.flags & USPosition)
            {
              /* don't constrain with placement algorithm */
              meta_topic (META_DEBUG_PLACEMENT,
                          "Honoring USPosition for %s instead of using placement algorithm\n", window->desc);

              goto done;
            }
          break;

          /* Ignore even USPosition on dialogs, splashscreen */
        case META_WINDOW_DIALOG:
        case META_WINDOW_MODAL_DIALOG:
        case META_WINDOW_SPLASHSCREEN:
          break;

          /* Assume the app knows best how to place these. */
        case META_WINDOW_DESKTOP:
        case META_WINDOW_DOCK:
        case META_WINDOW_TOOLBAR:
        case META_WINDOW_MENU:
        case META_WINDOW_UTILITY:
	/* override redirect window types: */
	case META_WINDOW_DROPDOWN_MENU:
	case META_WINDOW_POPUP_MENU:
	case META_WINDOW_TOOLTIP:
	case META_WINDOW_NOTIFICATION:
	case META_WINDOW_COMBO:
	case META_WINDOW_DND:
	case META_WINDOW_OVERRIDE_OTHER:
          if (window->size_hints.flags & PPosition)
            {
              meta_topic (META_DEBUG_PLACEMENT,
                          "Not placing non-normal non-dialog window with PPosition set\n");
              goto done;
            }
          break;
        }
    }
  else
    {
      /* workarounds enabled */

      if ((window->size_hints.flags & PPosition) ||
          (window->size_hints.flags & USPosition))
        {
          meta_topic (META_DEBUG_PLACEMENT,
                      "Not placing window with PPosition or USPosition set\n");
          avoid_being_obscured_as_second_modal_dialog (window, &x, &y);
          goto done;
        }
    }

  if (window->type == META_WINDOW_DIALOG ||
      window->type == META_WINDOW_MODAL_DIALOG)
    {
      MetaWindow *parent = meta_window_get_transient_for (window);

      if (parent)
        {
          MetaRectangle frame_rect, parent_frame_rect;

          meta_window_get_frame_rect (window, &frame_rect);
          meta_window_get_frame_rect (parent, &parent_frame_rect);

          y = parent_frame_rect.y;

          /* center of parent */
          x = parent_frame_rect.x + parent_frame_rect.width / 2;
          /* center of child over center of parent */
          x -= frame_rect.width / 2;

          /* "visually" center window over parent, leaving twice as
           * much space below as on top.
           */
          y += (parent_frame_rect.height - frame_rect.height)/3;

          meta_topic (META_DEBUG_PLACEMENT, "Centered window %s over transient parent\n",
                      window->desc);

          avoid_being_obscured_as_second_modal_dialog (window, &x, &y);

          goto done;
        }
    }

  /* FIXME UTILITY with transient set should be stacked up
   * on the sides of the parent window or something.
   */

  if (window_place_centered (window))
    {
      /* Center on current monitor */
      int w, h;
      MetaRectangle frame_rect;

      meta_window_get_frame_rect (window, &frame_rect);

      /* Warning, this function is a round trip! */
      xi = meta_screen_get_current_monitor_info (window->screen);

      w = xi->rect.width;
      h = xi->rect.height;

      x = (w - frame_rect.width) / 2;
      y = (h - frame_rect.height) / 2;

      x += xi->rect.x;
      y += xi->rect.y;

      meta_topic (META_DEBUG_PLACEMENT, "Centered window %s on screen %d monitor %d\n",
                  window->desc, window->screen->number, xi->number);

      goto done_check_denied_focus;
    }

  /* Find windows that matter (not minimized, on same workspace
   * as placed window, may be shaded - if shaded we pretend it isn't
   * for placement purposes)
   */
  {
    GSList *all_windows;
    GSList *tmp;

    all_windows = meta_display_list_windows (window->display, META_LIST_DEFAULT);

    tmp = all_windows;
    while (tmp != NULL)
      {
        MetaWindow *w = tmp->data;

        if (w != window &&
            meta_window_showing_on_its_workspace (w) &&
            meta_window_located_on_workspace (w, window->workspace))
          windows = g_list_prepend (windows, w);

        tmp = tmp->next;
      }

    g_slist_free (all_windows);
  }

  /* Warning, this is a round trip! */
  xi = meta_screen_get_current_monitor_info (window->screen);

  /* Maximize windows if they are too big for their work area (bit of
   * a hack here). Assume undecorated windows probably don't intend to
   * be maximized.
   */
  if (window->has_maximize_func && window->decorated &&
      !window->fullscreen)
    {
      MetaRectangle workarea;
      MetaRectangle frame_rect;

      meta_window_get_work_area_for_monitor (window,
                                             xi->number,
                                             &workarea);
      meta_window_get_frame_rect (window, &frame_rect);

      /* If the window is bigger than the screen, then automaximize.  Do NOT
       * auto-maximize the directions independently.  See #419810.
       */
      if (frame_rect.width >= workarea.width && frame_rect.height >= workarea.height)
        {
          window->maximize_horizontally_after_placement = TRUE;
          window->maximize_vertically_after_placement = TRUE;
        }
    }

  /* "Origin" placement algorithm */
  x = xi->rect.x;
  y = xi->rect.y;

  if (find_first_fit (window, windows,
                      xi->number,
                      x, y, &x, &y))
    goto done_check_denied_focus;

  /* No good fit? Fall back to cascading... */
  find_next_cascade (window, windows, x, y, &x, &y);

 done_check_denied_focus:
  /* If the window is being denied focus and isn't a transient of the
   * focus window, we do NOT want it to overlap with the focus window
   * if at all possible.  This is guaranteed to only be called if the
   * focus_window is non-NULL, and we try to avoid that window.
   */
  if (window->denied_focus_and_not_transient)
    {
      MetaWindow    *focus_window;
      gboolean       found_fit;

      focus_window = window->display->focus_window;
      g_assert (focus_window != NULL);

      /* No need to do anything if the window doesn't overlap at all */
      found_fit = !window_overlaps_focus_window (window);

      /* Try to do a first fit again, this time only taking into account the
       * focus window.
       */
      if (!found_fit)
        {
          GList *focus_window_list;
          focus_window_list = g_list_prepend (NULL, focus_window);

          /* Reset x and y ("origin" placement algorithm) */
          x = xi->rect.x;
          y = xi->rect.y;

          found_fit = find_first_fit (window, focus_window_list,
                                      xi->number,
                                      x, y, &x, &y);
          g_list_free (focus_window_list);
	}

      /* If that still didn't work, just place it where we can see as much
       * as possible.
       */
      if (!found_fit)
        find_most_freespace (window, focus_window, x, y, &x, &y);
    }

 done:
  if (windows)
    g_list_free (windows);

  *new_x = x;
  *new_y = y;
}
コード例 #30
0
ファイル: stack.c プロジェクト: mchalupa/mutter
/**
 * stack_sync_to_server:
 *
 * 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_xserver (MetaStack *stack)
{
  GArray *x11_stacked;
  GArray *all_root_children_stacked; /* wayland OR x11 */
  GList *tmp;
  GArray *x11_hidden_stack_ids;

  /* 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, in bottom-to-top order
   */
  x11_stacked = g_array_new (FALSE, FALSE, sizeof (Window));

  all_root_children_stacked = g_array_new (FALSE, FALSE, sizeof (guint64));
  x11_hidden_stack_ids = g_array_new (FALSE, FALSE, sizeof (guint64));

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

  for (tmp = g_list_last(stack->sorted); tmp != NULL; tmp = tmp->prev)
    {
      MetaWindow *w = tmp->data;
      Window top_level_window;
      guint64 stack_id;

      if (w->unmanaging)
        continue;

      meta_topic (META_DEBUG_STACK, "%u:%d - %s ",
		  w->layer, w->stack_position, w->desc);

      g_array_append_val (x11_stacked, w->xwindow);

      if (w->frame)
	top_level_window = w->frame->xwindow;
      else
	top_level_window = w->xwindow;

      if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
        stack_id = top_level_window;
      else
        stack_id = w->stamp;

      /* 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)
	{
          if (w->client_type == META_WINDOW_CLIENT_TYPE_X11)
            {
              guint64 stack_id = top_level_window;

              g_array_append_val (x11_hidden_stack_ids, stack_id);
            }
	  continue;
	}

      g_array_append_val (all_root_children_stacked, stack_id);
    }

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

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

  /* Sync to server */

  meta_topic (META_DEBUG_STACK, "Restacking %u windows\n",
              all_root_children_stacked->len);

  meta_stack_tracker_restack_managed (stack->screen->stack_tracker,
                                      (guint64 *)all_root_children_stacked->data,
                                      all_root_children_stacked->len);
  meta_stack_tracker_restack_at_bottom (stack->screen->stack_tracker,
                                        (guint64 *)x11_hidden_stack_ids->data,
                                        x11_hidden_stack_ids->len);

  /* 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->xwindows->data,
                   stack->xwindows->len);
  XChangeProperty (stack->screen->display->xdisplay,
                   stack->screen->xroot,
                   stack->screen->display->atom__NET_CLIENT_LIST_STACKING,
                   XA_WINDOW,
                   32, PropModeReplace,
                   (unsigned char *)x11_stacked->data,
                   x11_stacked->len);

  g_array_free (x11_stacked, TRUE);
  g_array_free (all_root_children_stacked, TRUE);
}