Ejemplo n.º 1
0
static void workspace_switch_sound(MetaWorkspace *from,
                                   MetaWorkspace *to) {

  MetaWorkspaceLayout layout;
  int i, nw, x, y, fi, ti;
  const char *e;

  nw = meta_screen_get_n_workspaces(from->screen);
  fi = meta_workspace_index(from);
  ti = meta_workspace_index(to);

  meta_screen_calc_workspace_layout(from->screen,
                                    nw,
                                    fi,
                                    &layout);

  for (i = 0; i < nw; i++)
    if (layout.grid[i] == ti)
      break;

  if (i >= nw) {
    meta_bug("Failed to find destination workspace in layout\n");
    goto finish;
  }

  y = i / layout.cols;
  x = i % layout.cols;

  /* We priorize horizontal over vertical movements here. The
     rationale for this is that horizontal movements are probably more
     interesting for sound effects because speakers are usually
     positioned on a horizontal and not a vertical axis. i.e. your
     spatial "Woosh!" effects will easily be able to encode horizontal
     movement but not such much vertical movement. */

  if (x < layout.current_col)
    e = "desktop-switch-left";
  else if (x > layout.current_col)
    e = "desktop-switch-right";
  else if (y < layout.current_row)
    e = "desktop-switch-up";
  else if (y > layout.current_row)
    e = "desktop-switch-down";
  else {
    meta_bug("Uh, origin and destination workspace at same logic position!\n");
    goto finish;
  }

#ifdef HAVE_CANBERRA
  ca_context_play(ca_gtk_context_get(), 1,
                  CA_PROP_EVENT_ID, e,
                  CA_PROP_EVENT_DESCRIPTION, "Desktop switched",
                  CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
                  NULL);
#endif

 finish:
  meta_screen_free_workspace_layout (&layout);
}
Ejemplo n.º 2
0
/**
 * meta_workspace_get_neighbor:
 * @workspace: a #MetaWorkspace
 * @direction: a #MetaMotionDirection, direction in which to look for the neighbor
 *
 * Gets the neighbor of the #MetaWorkspace in the given direction
 *
 * Return value: (transfer none): the neighbor #MetaWorkspace
 */
MetaWorkspace*
meta_workspace_get_neighbor (MetaWorkspace      *workspace,
                             MetaMotionDirection direction)
{
  MetaWorkspaceLayout layout;  
  int i, current_space, num_workspaces;
  gboolean ltr;

  current_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, &layout);

  meta_verbose ("Getting neighbor of %d in direction %s\n",
                current_space, meta_motion_direction_to_string (direction));
  
  ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR;

  switch (direction) 
    {
    case META_MOTION_LEFT:
      layout.current_col -= ltr ? 1 : -1;
      break;
    case META_MOTION_RIGHT:
      layout.current_col += ltr ? 1 : -1;
      break;
    case META_MOTION_UP:
      layout.current_row -= 1;
      break;
    case META_MOTION_DOWN:
      layout.current_row += 1;
      break;
    default:;
    }

  if (layout.current_col < 0)
    layout.current_col = 0;
  if (layout.current_col >= layout.cols)
    layout.current_col = layout.cols - 1;
  if (layout.current_row < 0)
    layout.current_row = 0;
  if (layout.current_row >= layout.rows)
    layout.current_row = layout.rows - 1;

  i = layout.grid[layout.current_row * layout.cols + layout.current_col];

  if (i < 0)
    i = current_space;

  if (i >= num_workspaces)
    meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid\n",
              i);
    
  meta_verbose ("Neighbor workspace is %d at row %d col %d\n",
                i, layout.current_row, layout.current_col);

  meta_screen_free_workspace_layout (&layout);
  
  return meta_screen_get_workspace_by_index (workspace->screen, i);
}
Ejemplo n.º 3
0
void
meta_prefs_remove_listener (MetaPrefsChangedFunc func,
                            gpointer             data)
{
    GList *tmp;

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

        if (l->func == func &&
                l->data == data)
        {
            g_free (l);
            listeners = g_list_delete_link (listeners, tmp);

            return;
        }

        tmp = tmp->next;
    }

    meta_bug ("Did not find listener to remove\n");
}
Ejemplo n.º 4
0
static int
x_io_error_handler (Display *xdisplay)
{
  MetaDisplay *display;

  display = meta_display_for_x_display (xdisplay);

  if (display == NULL)
    meta_bug ("IO error received for unknown display?\n");

  if (errno == EPIPE)
    {
      meta_warning (_("Lost connection to the display '%s';\n"
                      "most likely the X server was shut down or you killed/destroyed\n"
                      "the window manager.\n"),
                    display->name);
    }
  else
    {
      meta_warning (_("Fatal IO error %d (%s) on display '%s'.\n"),
                    errno, g_strerror (errno),
                    display->name);
    }

  /* Xlib would force an exit anyhow */
  exit (1);

  return 0;
}
Ejemplo n.º 5
0
void
meta_stack_remove (MetaStack  *stack,
                   MetaWindow *window)
{
  meta_topic (META_DEBUG_STACK, "Removing window %s from the stack\n", window->desc);

  if (window->stack_position < 0)
    meta_bug ("Window %s removed from stack but had no stack position\n",
              window->desc);

  /* Set window to top position, so removing it will not leave gaps
   * in the set of positions
   */
  meta_window_set_stack_position_no_sync (window,
                                          stack->n_positions - 1);
  window->stack_position = -1;
  stack->n_positions -= 1;

  /* We don't know if it's been moved from "added" to "stack" yet */
  stack->added = g_list_remove (stack->added, window);
  stack->sorted = g_list_remove (stack->sorted, window);

  /* Remember the window ID to remove it from the stack array.
   * The macro is safe to use: Window is guaranteed to be 32 bits, and
   * GUINT_TO_POINTER says it only works on 32 bits.
   */
  stack->removed = g_list_prepend (stack->removed,
                                   GUINT_TO_POINTER (window->xwindow));
  if (window->frame)
    stack->removed = g_list_prepend (stack->removed,
                                     GUINT_TO_POINTER (window->frame->xwindow));

  stack_sync_to_xserver (stack);
  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
Ejemplo n.º 6
0
static int
x_error_handler (Display     *xdisplay,
                 XErrorEvent *error)
{
  int retval;
  gchar buf[64];
  MetaDisplay *display;
  ForeignDisplay *foreign;

  for (foreign = foreign_displays; foreign != NULL; foreign = foreign->next)
  {
      if (foreign->dpy == xdisplay)
      {
	  foreign->handler (xdisplay, error, foreign->data);

	  return 0;
      }
  }

  XGetErrorText (xdisplay, error->error_code, buf, 63);

  display = meta_display_for_x_display (xdisplay);

  /* Display can be NULL here because the compositing manager
   * has its own Display, but Xlib only has one global error handler
   */
  if (display->error_traps > 0)
    {
      /* we're in an error trap, chain to the trap handler
       * saved from GDK
       */
      meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
                    buf,
                    error->serial,
                    error->error_code,
                    error->request_code,
                    error->minor_code);

      g_assert (display->error_trap_handler != NULL);
      g_assert (display->error_trap_handler != x_error_handler);

      retval = (* display->error_trap_handler) (xdisplay, error);
    }
  else
    {
      meta_bug ("Unexpected X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
                buf,
                error->serial,
                error->error_code,
                error->request_code,
                error->minor_code);

      retval = 1; /* compiler warning */
    }

  return retval;
}
Ejemplo n.º 7
0
static void
handle_preference_update_string (GSettings *settings,
                                 gchar *key)
{
    MetaStringPreference *cursor = preferences_string;
    char *value;
    gboolean inform_listeners = FALSE;

    while (cursor->base.key != NULL && strcmp (key, cursor->base.key) != 0)
        ++cursor;

    if (cursor->base.key==NULL)
        /* Didn't recognise that key. */
        return;

    /* Complex keys have a mapping function to check validity */
    if (cursor->handler)
    {
        if (cursor->target)
            meta_bug ("%s has both a target and a handler\n", cursor->base.key);

        g_settings_get_mapped (SETTINGS (cursor->base.schema),
                               cursor->base.key, cursor->handler, NULL);
    }
    else
    {
        if (!cursor->target)
            meta_bug ("%s must have handler or target\n", cursor->base.key);

        value = g_settings_get_string (SETTINGS (cursor->base.schema),
                                       cursor->base.key);
        inform_listeners = (g_strcmp0 (value, *(cursor->target)) != 0);

        if (*(cursor->target))
            g_free (*(cursor->target));

        *(cursor->target) = value;
    }

    if (inform_listeners)
        queue_changed (cursor->base.pref);
}
Ejemplo n.º 8
0
int
meta_workspace_index (MetaWorkspace *workspace)
{
  int ret;

  ret = g_list_index (workspace->screen->workspaces, workspace);

  if (ret < 0)
    meta_bug ("Workspace does not exist to index!\n");

  return ret;
}
Ejemplo n.º 9
0
static void
meta_barrier_dispose (GObject *object)
{
  MetaBarrier *barrier = META_BARRIER (object);

  if (meta_barrier_is_active (barrier))
    {
      meta_bug ("MetaBarrier %p was destroyed while it was still active.",
                barrier);
    }

  G_OBJECT_CLASS (meta_barrier_parent_class)->dispose (object);
}
Ejemplo n.º 10
0
/* Looks up the MetaWindow representing the frame of the given X window.
 * Used as a helper function by a bunch of the functions below.
 *
 * FIXME: The functions that use this function throw the result away
 * after use. Many of these functions tend to be called in small groups,
 * which results in get_window() getting called several times in succession
 * with the same parameters. We should profile to see whether this wastes
 * much time, and if it does we should look into a generalised
 * meta_core_get_window_info() which takes a bunch of pointers to variables
 * to put its results in, and only fills in the non-null ones.
 */
static MetaWindow *
get_window (Display *xdisplay,
            Window   frame_xwindow)
{
  MetaDisplay *display;
  MetaWindow *window;
  
  display = meta_display_for_x_display (xdisplay);
  window = meta_display_lookup_x_window (display, frame_xwindow);

  if (window == NULL || window->frame == NULL)
    {
      meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
      return NULL;
    }

  return window;
}
Ejemplo n.º 11
0
void
meta_stack_add (MetaStack  *stack,
                MetaWindow *window)
{
  meta_topic (META_DEBUG_STACK, "Adding window %s to the stack\n", window->desc);

  if (window->stack_position >= 0)
    meta_bug ("Window %s had stack position already\n", window->desc);
  
  stack->added = g_list_prepend (stack->added, window);

  window->stack_position = stack->n_positions;
  stack->n_positions += 1;
  meta_topic (META_DEBUG_STACK,
              "Window %s has stack_position initialized to %d\n",
              window->desc, window->stack_position);
  
  stack_sync_to_server (stack);
}
Ejemplo n.º 12
0
LOCAL_SYMBOL void
meta_stack_add (MetaStack  *stack,
                MetaWindow *window)
{
  meta_topic (META_DEBUG_STACK, "Adding window %s to the stack\n", window->desc);

  if (window->stack_position >= 0)
    meta_bug ("Window %s had stack position already\n", window->desc);
  
  stack->added = g_list_prepend (stack->added, window);

  window->stack_position = stack->n_positions;
  stack->n_positions += 1;
  meta_topic (META_DEBUG_STACK,
              "Window %s has stack_position initialized to %d\n",
              window->desc, window->stack_position);
  
  stack_sync_to_server (stack);
  meta_stack_update_window_tile_matches (stack, window->screen->active_workspace);
}
Ejemplo n.º 13
0
void
meta_prop_get_values (MetaDisplay   *display,
                      Window         xwindow,
                      MetaPropValue *values,
                      int            n_values)
{
  int i;
  AgGetPropertyTask **tasks;

  meta_verbose ("Requesting %d properties of 0x%lx at once\n",
                n_values, xwindow);
  
  if (n_values == 0)
    return;
  
  tasks = g_new0 (AgGetPropertyTask*, n_values);

  /* Start up tasks. The "values" array can have values
   * with atom == None, which means to ignore that element.
   */
  i = 0;
  while (i < n_values)
    {
      if (values[i].required_type == None)
        {
          switch (values[i].type)
            {
            case META_PROP_VALUE_INVALID:
              /* This means we don't really want a value, e.g. got
               * property notify on an atom we don't care about.
               */
              if (values[i].atom != None)
                meta_bug ("META_PROP_VALUE_INVALID requested in %s\n", G_STRFUNC);
              break;
            case META_PROP_VALUE_UTF8_LIST:
            case META_PROP_VALUE_UTF8:
              values[i].required_type = display->atom_UTF8_STRING;
              break;
            case META_PROP_VALUE_STRING:
            case META_PROP_VALUE_STRING_AS_UTF8:
              values[i].required_type = XA_STRING;
              break;
            case META_PROP_VALUE_MOTIF_HINTS:
              values[i].required_type = AnyPropertyType;
              break;
            case META_PROP_VALUE_CARDINAL_LIST:
            case META_PROP_VALUE_CARDINAL:
              values[i].required_type = XA_CARDINAL;
              break;
            case META_PROP_VALUE_WINDOW:
              values[i].required_type = XA_WINDOW;
              break;
            case META_PROP_VALUE_ATOM_LIST:
              values[i].required_type = XA_ATOM;
              break;
            case META_PROP_VALUE_TEXT_PROPERTY:
              values[i].required_type = AnyPropertyType;
              break;
            case META_PROP_VALUE_WM_HINTS:
              values[i].required_type = XA_WM_HINTS;
              break;
            case META_PROP_VALUE_CLASS_HINT:
              values[i].required_type = XA_STRING;
              break;
            case META_PROP_VALUE_SIZE_HINTS:
              values[i].required_type = XA_WM_SIZE_HINTS;
              break;
            case META_PROP_VALUE_SYNC_COUNTER:
	      values[i].required_type = XA_CARDINAL;
              break;
            }
        }

      if (values[i].atom != None)
        tasks[i] = get_task (display, xwindow,
                             values[i].atom, values[i].required_type);
      
      ++i;
    }  
  
  /* Get replies for all our tasks */
  meta_topic (META_DEBUG_SYNC, "Syncing to get %d GetProperty replies in %s\n",
              n_values, G_STRFUNC);
  XSync (display->xdisplay, False);
  
  /* Collect results, should arrive in order requested */
  i = 0;
  while (i < n_values)
    {
      AgGetPropertyTask *task;
      GetPropertyResults results;
      
      if (tasks[i] == NULL)
        {
          /* Probably values[i].type was None, or ag_task_create()
           * returned NULL.
           */
          values[i].type = META_PROP_VALUE_INVALID;
          goto next;
        }
      
      task = ag_get_next_completed_task (display->xdisplay);
      g_assert (task != NULL);
      g_assert (ag_task_have_reply (task));

      results.display = display;
      results.xwindow = xwindow;
      results.xatom = values[i].atom;
      results.prop = NULL;
      results.n_items = 0;
      results.type = None;
      results.bytes_after = 0;
      results.format = 0;
      
      if (ag_task_get_reply_and_free (task,
                                      &results.type, &results.format,
                                      &results.n_items,
                                      &results.bytes_after,
                                      &results.prop) != Success ||
          results.type == None)
        {
          values[i].type = META_PROP_VALUE_INVALID;
          if (results.prop)
            {
              XFree (results.prop);
              results.prop = NULL;
            }
          goto next;
        }

      switch (values[i].type)
        {
        case META_PROP_VALUE_INVALID:
          g_assert_not_reached ();
          break;
        case META_PROP_VALUE_UTF8_LIST:
          if (!utf8_list_from_results (&results,
                                       &values[i].v.string_list.strings,
                                       &values[i].v.string_list.n_strings))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_UTF8:
          if (!utf8_string_from_results (&results,
                                         &values[i].v.str))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_STRING:
          if (!latin1_string_from_results (&results,
                                           &values[i].v.str))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_STRING_AS_UTF8:
          if (!latin1_string_from_results (&results,
                                           &values[i].v.str))
            values[i].type = META_PROP_VALUE_INVALID;
          else
            {
              char *new_str;
              char *xmalloc_new_str;

              new_str = latin1_to_utf8 (values[i].v.str);
              xmalloc_new_str = ag_Xmalloc (strlen (new_str) + 1);
              if (xmalloc_new_str != NULL)
                {
                  strcpy (xmalloc_new_str, new_str);
                  meta_XFree (values[i].v.str);
                  values[i].v.str = xmalloc_new_str;
                }

              g_free (new_str);
            }
          break;
        case META_PROP_VALUE_MOTIF_HINTS:
          if (!motif_hints_from_results (&results,
                                         &values[i].v.motif_hints))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_CARDINAL_LIST:
          if (!cardinal_list_from_results (&results,
                                           &values[i].v.cardinal_list.cardinals,
                                           &values[i].v.cardinal_list.n_cardinals))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_CARDINAL:
          if (!cardinal_with_atom_type_from_results (&results,
                                                     values[i].required_type,
                                                     &values[i].v.cardinal))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_WINDOW:
          if (!window_from_results (&results,
                                    &values[i].v.xwindow))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_ATOM_LIST:
          if (!atom_list_from_results (&results,
                                       &values[i].v.atom_list.atoms,
                                       &values[i].v.atom_list.n_atoms))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_TEXT_PROPERTY:
          if (!text_property_from_results (&results, &values[i].v.str))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_WM_HINTS:
          if (!wm_hints_from_results (&results, &values[i].v.wm_hints))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_CLASS_HINT:
          if (!class_hint_from_results (&results, &values[i].v.class_hint))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_SIZE_HINTS:
          if (!size_hints_from_results (&results,
                                        &values[i].v.size_hints.hints,
                                        &values[i].v.size_hints.flags))
            values[i].type = META_PROP_VALUE_INVALID;
          break;
        case META_PROP_VALUE_SYNC_COUNTER:
#ifdef HAVE_XSYNC
          if (!counter_from_results (&results,
                                     &values[i].v.xcounter))
            values[i].type = META_PROP_VALUE_INVALID;
#else
          values[i].type = META_PROP_VALUE_INVALID;
          if (results.prop)
            {
              XFree (results.prop);
              results.prop = NULL;
            }
#endif
          break;
        }

    next:
      ++i;
    }

  g_free (tasks);
}
Ejemplo n.º 14
0
void
meta_core_get (Display *xdisplay,
    Window xwindow,
    ...)
{
  va_list args;
  MetaCoreGetType request;

  MetaDisplay *display = meta_display_for_x_display (xdisplay);
  MetaWindow *window = meta_display_lookup_x_window (display, xwindow);

  va_start (args, xwindow);

  request = va_arg (args, MetaCoreGetType);

  /* Now, we special-case the first request slightly. Mostly, requests
   * for information on windows which have no frame are errors.
   * But sometimes we may want to know *whether* a window has a frame.
   * In this case, pass the key META_CORE_WINDOW_HAS_FRAME
   * as the *first* request, with a pointer to a boolean; if the window
   * has no frame, this will be set to False and meta_core_get will
   * exit immediately (so the values of any other requests will be
   * undefined). Otherwise it will be set to True and meta_core_get will
   * continue happily on its way.
   */

  if (request != META_CORE_WINDOW_HAS_FRAME &&
      (window == NULL || window->frame == NULL)) {
    meta_bug ("No such frame window 0x%lx!\n", xwindow);
    return;
  }

  while (request != META_CORE_GET_END) {
    
    gpointer answer = va_arg (args, gpointer);

    switch (request) {
      case META_CORE_WINDOW_HAS_FRAME:
        *((gboolean*)answer) = window != NULL && window->frame != NULL;
        if (!*((gboolean*)answer)) return; /* see above */
        break; 
      case META_CORE_GET_CLIENT_WIDTH:
        *((gint*)answer) = window->rect.width;
        break;
      case META_CORE_GET_CLIENT_HEIGHT:
        *((gint*)answer) = window->rect.height;
        break;
      case META_CORE_GET_CLIENT_XWINDOW:
        *((Window*)answer) = window->xwindow;
        break;
      case META_CORE_GET_FRAME_FLAGS:
        *((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
        break; 
      case META_CORE_GET_FRAME_TYPE:
        *((MetaFrameType*)answer) = meta_window_get_frame_type (window);
        break;
      case META_CORE_GET_MINI_ICON:
        *((GdkPixbuf**)answer) = window->mini_icon;
        break;
      case META_CORE_GET_ICON:
        *((GdkPixbuf**)answer) = window->icon;
        break;
      case META_CORE_GET_X:
        meta_window_get_position (window, (int*)answer, NULL);
        break;
      case META_CORE_GET_Y:
        meta_window_get_position (window, NULL, (int*)answer);
        break;
      case META_CORE_GET_FRAME_WORKSPACE:
        *((gint*)answer) = meta_window_get_net_wm_desktop (window);
        break;
      case META_CORE_GET_FRAME_X:
        *((gint*)answer) = window->frame->rect.x;
        break;
      case META_CORE_GET_FRAME_Y:
        *((gint*)answer) = window->frame->rect.y;
        break;
      case META_CORE_GET_FRAME_WIDTH:
        *((gint*)answer) = window->frame->rect.width;
        break;
      case META_CORE_GET_FRAME_HEIGHT:
        *((gint*)answer) = window->frame->rect.height;
        break;
      case META_CORE_GET_THEME_VARIANT:
        *((char**)answer) = window->gtk_theme_variant;
        break;
      case META_CORE_GET_SCREEN_WIDTH:
        *((gint*)answer) = window->screen->rect.width;
        break;
      case META_CORE_GET_SCREEN_HEIGHT:
        *((gint*)answer) = window->screen->rect.height;
        break;

      default:
        meta_warning(_("Unknown window information request: %d"), request);
    }

    request = va_arg (args, MetaCoreGetType);
  } 

  va_end (args);
}
Ejemplo n.º 15
0
void
meta_core_get (Display *xdisplay,
    Window xwindow,
    ...)
{
  va_list args;
  MetaCoreGetType request;

  MetaDisplay *display = meta_display_for_x_display (xdisplay);
  MetaWindow *window = meta_display_lookup_x_window (display, xwindow);

  va_start (args, xwindow);

  request = va_arg (args, MetaCoreGetType);

  /* Now, we special-case the first request slightly. Mostly, requests
   * for information on windows which have no frame are errors.
   * But sometimes we may want to know *whether* a window has a frame.
   * In this case, pass the key META_CORE_WINDOW_HAS_FRAME
   * as the *first* request, with a pointer to a boolean; if the window
   * has no frame, this will be set to False and meta_core_get will
   * exit immediately (so the values of any other requests will be
   * undefined). Otherwise it will be set to True and meta_core_get will
   * continue happily on its way.
   */

  if (request != META_CORE_WINDOW_HAS_FRAME &&
      (window == NULL || window->frame == NULL)) {
    meta_bug ("No such frame window 0x%lx!\n", xwindow);
    return;
  }

  while (request != META_CORE_GET_END) {
    
    gpointer answer = va_arg (args, gpointer);

    switch (request) {
      case META_CORE_WINDOW_HAS_FRAME:
        *((gboolean*)answer) = window != NULL && window->frame != NULL;
        if (!*((gboolean*)answer)) return; /* see above */
        break; 
      case META_CORE_GET_CLIENT_WIDTH:
        *((gint*)answer) = window->rect.width;
        break;
      case META_CORE_GET_CLIENT_HEIGHT:
        *((gint*)answer) = window->rect.height;
        break;
      case META_CORE_IS_TITLEBAR_ONSCREEN:
        *((gboolean*)answer) = meta_window_titlebar_is_onscreen (window);
        break;
      case META_CORE_GET_CLIENT_XWINDOW:
        *((Window*)answer) = window->xwindow;
        break;
      case META_CORE_GET_FRAME_FLAGS:
        *((MetaFrameFlags*)answer) = meta_frame_get_flags (window->frame);
        break; 
      case META_CORE_GET_FRAME_TYPE:
          {
          MetaFrameType base_type = META_FRAME_TYPE_LAST;

          switch (window->type)
            {
            case META_WINDOW_NORMAL:
              base_type = META_FRAME_TYPE_NORMAL;
              break;

            case META_WINDOW_DIALOG:
              base_type = META_FRAME_TYPE_DIALOG;
              break;

            case META_WINDOW_MODAL_DIALOG:
              base_type = META_FRAME_TYPE_MODAL_DIALOG;
              break;

            case META_WINDOW_MENU:
              base_type = META_FRAME_TYPE_MENU;
              break;

            case META_WINDOW_UTILITY:
              base_type = META_FRAME_TYPE_UTILITY;
              break;

            case META_WINDOW_DESKTOP:
            case META_WINDOW_DOCK:
            case META_WINDOW_TOOLBAR:
            case META_WINDOW_SPLASHSCREEN:
              /* No frame */
              base_type = META_FRAME_TYPE_LAST;
              break;

            }

          if (base_type == META_FRAME_TYPE_LAST)
            {
              /* can't add border if undecorated */
              *((MetaFrameType*)answer) = META_FRAME_TYPE_LAST; 
            }
          else if (window->border_only)
            {
              /* override base frame type */
              *((MetaFrameType*)answer) = META_FRAME_TYPE_BORDER; 
            }
          else
            {
              *((MetaFrameType*)answer) = base_type;
            }

          break; 
          }
      case META_CORE_GET_MINI_ICON:
        *((GdkPixbuf**)answer) = window->mini_icon;
        break;
      case META_CORE_GET_ICON:
        *((GdkPixbuf**)answer) = window->icon;
        break;
      case META_CORE_GET_X:
        meta_window_get_position (window, (int*)answer, NULL);
        break;
      case META_CORE_GET_Y:
        meta_window_get_position (window, NULL, (int*)answer);
        break;
      case META_CORE_GET_FRAME_WORKSPACE:
        *((gint*)answer) = meta_window_get_net_wm_desktop (window);
        break;
      case META_CORE_GET_FRAME_X:
        *((gint*)answer) = window->frame->rect.x;
        break;
      case META_CORE_GET_FRAME_Y:
        *((gint*)answer) = window->frame->rect.y;
        break;
      case META_CORE_GET_FRAME_WIDTH:
        *((gint*)answer) = window->frame->rect.width;
        break;
      case META_CORE_GET_FRAME_HEIGHT:
        *((gint*)answer) = window->frame->rect.height;
        break;
      case META_CORE_GET_SCREEN_WIDTH:
        *((gint*)answer) = window->screen->rect.width;
        break;
      case META_CORE_GET_SCREEN_HEIGHT:
        *((gint*)answer) = window->screen->rect.height;
        break;

      default:
        meta_warning(_("Unknown window information request: %d"), request);
    }

    request = va_arg (args, MetaCoreGetType);
  } 

  va_end (args);
}
MetaWorkspace*
meta_workspace_get_neighbor (MetaWorkspace      *workspace,
                             MetaMotionDirection direction)
{
  MetaWorkspaceLayout layout;
  int i, current_space, num_workspaces;
  gboolean ltr;
  MetaWrapStyle wrap;

  current_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, &layout);
  wrap = meta_prefs_get_wrap_style();

  meta_verbose ("Getting neighbor of %d in direction %s\n",
                current_space, meta_motion_direction_to_string (direction));

  ltr = meta_ui_get_direction() == META_UI_DIRECTION_LTR;

  switch (direction)
    {
    case META_MOTION_LEFT:
      layout.current_col -= ltr ? 1 : -1;
      break;
    case META_MOTION_RIGHT:
      layout.current_col += ltr ? 1 : -1;
      break;
    case META_MOTION_UP:
      layout.current_row -= 1;
      break;
    case META_MOTION_DOWN:
      layout.current_row += 1;
      break;
    }

  /* LEFT */
  if (layout.current_col < 0)
    switch (wrap)
      {
      case META_WRAP_NONE:
        layout.current_col = 0;
        break;
      case META_WRAP_TOROIDAL:
        layout.current_row = layout.current_row > 0 ? layout.current_row - 1 : layout.rows - 1;
        /* fall through */
      case META_WRAP_CLASSIC:
        layout.current_col = layout.cols - 1;
      }
  /* RIGHT */
  if (layout.current_col >= layout.cols)
    switch (wrap)
      {
      case META_WRAP_NONE:
        layout.current_col = layout.cols - 1;
        break;
      case META_WRAP_TOROIDAL:
        layout.current_row = layout.current_row < layout.rows - 1 ? layout.current_row + 1 : 0;
        /* fall through */
      case META_WRAP_CLASSIC:
        layout.current_col = 0;
      }
  /* UP */
  if (layout.current_row < 0)
    switch (wrap)
      {
      case META_WRAP_NONE:
        layout.current_row = 0;
        break;
      case META_WRAP_TOROIDAL:
        layout.current_col = layout.current_col > 0 ? layout.current_col - 1 : layout.cols - 1;
        /* fall through */
      case META_WRAP_CLASSIC:
        layout.current_row = layout.rows - 1;
      }
  /* DOWN */
  if (layout.current_row >= layout.rows)
    switch (wrap)
      {
      case META_WRAP_NONE:
        layout.current_row = layout.rows - 1;
        break;
      case META_WRAP_TOROIDAL:
        layout.current_col = layout.current_col < layout.cols - 1 ? layout.current_col + 1 : 0;
        /* fall through */
      case META_WRAP_CLASSIC:
        layout.current_row = 0;
      }

  /* If we have an uneven arrangement of workspaces, (layout.cols - n, layout.rows - 1) may be an invalid workspace
     e.g. we have 7 workspaces on a 3x3 pane */
  if (wrap != META_WRAP_NONE && (layout.current_row * layout.cols + layout.current_col >= num_workspaces))
    switch (direction)
      {
      case META_MOTION_LEFT:
        layout.current_col = num_workspaces - (layout.current_row * layout.cols + 1);
        break;
      case META_MOTION_RIGHT:
       layout.current_col = 0;
       if (wrap == META_WRAP_TOROIDAL)
         layout.current_row = 0;
       break;
      case META_MOTION_UP:
        layout.current_row -= 1;
        break;
      case META_MOTION_DOWN:
        layout.current_row = 0;
        if (wrap == META_WRAP_TOROIDAL)
	  layout.current_col = layout.current_col < layout.cols - 1 ? layout.current_col + 1 : 0;
        break;
      }

  i = layout.grid[layout.current_row * layout.cols + layout.current_col];

  if (i < 0)
    i = current_space;

  if (i >= num_workspaces)
    meta_bug ("calc_workspace_layout left an invalid (too-high) workspace number %d in the grid\n",
              i);

  meta_verbose ("Neighbor workspace is %d at row %d col %d\n",
                i, layout.current_row, layout.current_col);

  meta_screen_free_workspace_layout (&layout);

  return meta_screen_get_workspace_by_index (workspace->screen, i);
}
Ejemplo n.º 17
0
void
meta_session_init (const char *previous_client_id,
                   const char *previous_save_file)
{
  /* Some code here from twm */
  char buf[256];
  unsigned long mask;
  SmcCallbacks callbacks;
  char *saved_client_id;
  
  meta_topic (META_DEBUG_SM, "Initializing session with save file '%s'\n",
              previous_save_file ? previous_save_file : "(none)");

  if (previous_save_file)
    {
      saved_client_id = load_state (previous_save_file);
      previous_client_id = saved_client_id;
    }
  else if (previous_client_id)
    {
      char *save_file = g_strconcat (previous_client_id, ".ms", NULL);
      saved_client_id = load_state (save_file);
      g_free (save_file);
    }
  else
    {
      saved_client_id = NULL;
    }
  
  ice_init ();
  
  mask = SmcSaveYourselfProcMask | SmcDieProcMask |
    SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
  
  callbacks.save_yourself.callback = save_yourself_callback;
  callbacks.save_yourself.client_data = NULL;
  
  callbacks.die.callback = die_callback;
  callbacks.die.client_data = NULL;
  
  callbacks.save_complete.callback = save_complete_callback;
  callbacks.save_complete.client_data = NULL;
  
  callbacks.shutdown_cancelled.callback = shutdown_cancelled_callback;
  callbacks.shutdown_cancelled.client_data = NULL;
  
  session_connection =
    SmcOpenConnection (NULL, /* use SESSION_MANAGER env */
                       NULL, /* means use existing ICE connection */
                       SmProtoMajor,
                       SmProtoMinor,
                       mask,
                       &callbacks,
                       (char*) previous_client_id,
                       &client_id,
                       255, buf);
  
  if (session_connection == NULL)
    {
      meta_topic (META_DEBUG_SM, 
                  "Failed to a open connection to a session manager, so window positions will not be saved: %s\n",
                  buf);

      goto out;
    }
  else
    {
      if (client_id == NULL)
        meta_bug ("Session manager gave us a NULL client ID?");
      meta_topic (META_DEBUG_SM, "Obtained session ID '%s'\n", client_id);
    }

  if (previous_client_id && strcmp (previous_client_id, client_id) == 0)
    current_state = STATE_IDLE;
  else
    current_state = STATE_REGISTERING;
  
  {
    SmProp prop1, prop2, prop3, prop4, prop5, prop6, *props[6];
    SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val, prop6val;
    char pid[32];
    char hint = SmRestartImmediately;
    char priority = 20; /* low to run before other apps */
    
    prop1.name = SmProgram;
    prop1.type = SmARRAY8;
    prop1.num_vals = 1;
    prop1.vals = &prop1val;
    prop1val.value = "consortium";
    prop1val.length = strlen ("consortium");

    /* twm sets getuid() for this, but the SM spec plainly
     * says pw_name, twm is on crack
     */
    prop2.name = SmUserID;
    prop2.type = SmARRAY8;
    prop2.num_vals = 1;
    prop2.vals = &prop2val;
    prop2val.value = (char*) g_get_user_name ();
    prop2val.length = strlen (prop2val.value);
	
    prop3.name = SmRestartStyleHint;
    prop3.type = SmCARD8;
    prop3.num_vals = 1;
    prop3.vals = &prop3val;
    prop3val.value = &hint;
    prop3val.length = 1;

    sprintf (pid, "%d", getpid ());
    prop4.name = SmProcessID;
    prop4.type = SmARRAY8;
    prop4.num_vals = 1;
    prop4.vals = &prop4val;
    prop4val.value = pid;
    prop4val.length = strlen (prop4val.value);    

    /* Always start in home directory */
    prop5.name = SmCurrentDirectory;
    prop5.type = SmARRAY8;
    prop5.num_vals = 1;
    prop5.vals = &prop5val;
    prop5val.value = (char*) g_get_home_dir ();
    prop5val.length = strlen (prop5val.value);

    prop6.name = "_GSM_Priority";
    prop6.type = SmCARD8;
    prop6.num_vals = 1;
    prop6.vals = &prop6val;
    prop6val.value = &priority;
    prop6val.length = 1;
    
    props[0] = &prop1;
    props[1] = &prop2;
    props[2] = &prop3;
    props[3] = &prop4;
    props[4] = &prop5;
    props[5] = &prop6;
    
    SmcSetProperties (session_connection, 6, props);
  }

 out:
  g_free (saved_client_id);
}
Ejemplo n.º 18
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... */
}