Esempio n. 1
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);
}
Esempio n. 2
0
static void popup_position_func(GtkMenu* menu, gint* x, gint* y, gboolean* push_in, gpointer user_data)
{
	GtkRequisition req;
	GdkPoint* pos;

	pos = user_data;

#if GTK_CHECK_VERSION (3, 0, 0)
	gtk_widget_get_preferred_size (GTK_WIDGET (menu), &req, NULL);
#else
	gtk_widget_size_request(GTK_WIDGET(menu), &req);
#endif

	*x = pos->x;
	*y = pos->y;

	if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
	{
		*x = MAX (0, *x - req.width);
	}

	/* Ensure onscreen */
	*x = CLAMP (*x, 0, MAX(0, gdk_screen_width() - req.width));
	*y = CLAMP (*y, 0, MAX(0, gdk_screen_height() - req.height));
}
void
meta_fixed_tip_show (Display *xdisplay, int screen_number,
                     int root_x, int root_y,
                     const char *markup_text)
{
  int w, h;
  
  if (tip == NULL)
    {      
      tip = gtk_window_new (GTK_WINDOW_POPUP);
      gtk_window_set_type_hint (GTK_WINDOW(tip), GDK_WINDOW_TYPE_HINT_TOOLTIP);

      {
        GdkScreen *gdk_screen;
	GdkRectangle monitor;
	gint mon_num;

        gdk_screen = gdk_display_get_screen (gdk_display_get_default (),
                                             screen_number);
        gtk_window_set_screen (GTK_WINDOW (tip),
                               gdk_screen);
	mon_num = gdk_screen_get_monitor_at_point (gdk_screen, root_x, root_y);
	gdk_screen_get_monitor_geometry (gdk_screen, mon_num, &monitor);
	screen_right_edge = monitor.x + monitor.width;
	screen_bottom_edge = monitor.y + monitor.height;
      }
      
      gtk_widget_set_app_paintable (tip, TRUE);
      gtk_window_set_resizable (GTK_WINDOW (tip), FALSE);
      gtk_widget_set_name (tip, "gtk-tooltips");
      gtk_container_set_border_width (GTK_CONTAINER (tip), 4);

      g_signal_connect_swapped (tip, "expose_event",
				 G_CALLBACK (expose_handler), NULL);

      label = gtk_label_new (NULL);
      gtk_label_set_line_wrap (GTK_LABEL (label), TRUE);
      gtk_misc_set_alignment (GTK_MISC (label), 0.5, 0.5);
      gtk_widget_show (label);
      
      gtk_container_add (GTK_CONTAINER (tip), label);

      g_signal_connect (tip, "destroy",
			G_CALLBACK (gtk_widget_destroyed), &tip);
    }

  gtk_label_set_markup (GTK_LABEL (label), markup_text);
  
  gtk_window_get_size (GTK_WINDOW (tip), &w, &h);

  if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
      root_x = MAX(0, root_x - w);

  if ((root_x + w) > screen_right_edge)
    root_x -= (root_x + w) - screen_right_edge;
  
  gtk_window_move (GTK_WINDOW (tip), root_x, root_y);

  gtk_widget_show (tip);
}
Esempio n. 4
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);
}
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);
}
Esempio n. 6
0
static gboolean
button_layout_handler (GVariant *value,
                       gpointer *result,
                       gpointer  data)
{
    MetaButtonLayout new_layout;
    const gchar *string_value;
    char **sides = NULL;
    int i;

    /* We need to ignore unknown button functions, for
     * compat with future versions
     */

    *result = NULL; /* ignored */
    string_value = g_variant_get_string (value, NULL);

    if (string_value)
        sides = g_strsplit (string_value, ":", 2);

    i = 0;

    if (sides != NULL && sides[0] != NULL)
    {
        char **buttons;
        int b;
        gboolean used[META_BUTTON_FUNCTION_LAST];

        while (i < META_BUTTON_FUNCTION_LAST)
        {
            used[i] = FALSE;
            new_layout.left_buttons_has_spacer[i] = FALSE;
            i++;
        }

        buttons = g_strsplit (sides[0], ",", -1);
        i = 0;
        b = 0;
        while (buttons[b] != NULL)
        {
            MetaButtonFunction f = button_function_from_string (buttons[b]);
            if (i > 0 && strcmp("spacer", buttons[b]) == 0)
            {
                new_layout.left_buttons_has_spacer[i-1] = TRUE;
                f = button_opposite_function (f);

                if (f != META_BUTTON_FUNCTION_LAST)
                {
                    new_layout.left_buttons_has_spacer[i-2] = TRUE;
                }
            }
            else
            {
                if (f != META_BUTTON_FUNCTION_LAST && !used[f])
                {
                    new_layout.left_buttons[i] = f;
                    used[f] = TRUE;
                    i++;

                    f = button_opposite_function (f);

                    if (f != META_BUTTON_FUNCTION_LAST)
                        new_layout.left_buttons[i++] = f;

                }
                else
                {
                    meta_topic (META_DEBUG_PREFS, "Ignoring unknown or already-used button name \"%s\"\n",
                                buttons[b]);
                }
            }

            ++b;
        }

        g_strfreev (buttons);
    }

    /* Close the buttons list even if it's empty */
    new_layout.left_buttons[i] = META_BUTTON_FUNCTION_LAST;
    new_layout.left_buttons_has_spacer[i] = FALSE;


    i = 0;

    if (sides != NULL && sides[0] != NULL && sides[1] != NULL)
    {
        char **buttons;
        int b;
        gboolean used[META_BUTTON_FUNCTION_LAST];

        while (i < META_BUTTON_FUNCTION_LAST)
        {
            used[i] = FALSE;
            new_layout.right_buttons_has_spacer[i] = FALSE;
            i++;
        }

        buttons = g_strsplit (sides[1], ",", -1);
        i = 0;
        b = 0;
        while (buttons[b] != NULL)
        {
            MetaButtonFunction f = button_function_from_string (buttons[b]);
            if (i > 0 && strcmp("spacer", buttons[b]) == 0)
            {
                new_layout.right_buttons_has_spacer[i-1] = TRUE;
                f = button_opposite_function (f);
                if (f != META_BUTTON_FUNCTION_LAST)
                {
                    new_layout.right_buttons_has_spacer[i-2] = TRUE;
                }
            }
            else
            {
                if (f != META_BUTTON_FUNCTION_LAST && !used[f])
                {
                    new_layout.right_buttons[i] = f;
                    used[f] = TRUE;
                    i++;

                    f = button_opposite_function (f);

                    if (f != META_BUTTON_FUNCTION_LAST)
                        new_layout.right_buttons[i++] = f;

                }
                else
                {
                    meta_topic (META_DEBUG_PREFS, "Ignoring unknown or already-used button name \"%s\"\n",
                                buttons[b]);
                }
            }

            ++b;
        }

        g_strfreev (buttons);
    }

    /* Close the buttons list even if it's empty */
    new_layout.right_buttons[i] = META_BUTTON_FUNCTION_LAST;
    new_layout.right_buttons_has_spacer[i] = FALSE;

    if (sides)
        g_strfreev (sides);

    /* Invert the button layout for RTL languages */
    if (meta_ui_get_direction() == META_UI_DIRECTION_RTL)
    {
        MetaButtonLayout rtl_layout;
        int j;

        for (i = 0; new_layout.left_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
        for (j = 0; j < i; j++)
        {
            rtl_layout.right_buttons[j] = new_layout.left_buttons[i - j - 1];
            if (j == 0)
                rtl_layout.right_buttons_has_spacer[i - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
            else
                rtl_layout.right_buttons_has_spacer[j - 1] = new_layout.left_buttons_has_spacer[i - j - 1];
        }
        rtl_layout.right_buttons[j] = META_BUTTON_FUNCTION_LAST;
        rtl_layout.right_buttons_has_spacer[j] = FALSE;

        for (i = 0; new_layout.right_buttons[i] != META_BUTTON_FUNCTION_LAST; i++);
        for (j = 0; j < i; j++)
        {
            rtl_layout.left_buttons[j] = new_layout.right_buttons[i - j - 1];
            if (j == 0)
                rtl_layout.left_buttons_has_spacer[i - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
            else
                rtl_layout.left_buttons_has_spacer[j - 1] = new_layout.right_buttons_has_spacer[i - j - 1];
        }
        rtl_layout.left_buttons[j] = META_BUTTON_FUNCTION_LAST;
        rtl_layout.left_buttons_has_spacer[j] = FALSE;

        new_layout = rtl_layout;
    }

    if (!button_layout_equal (&button_layout, &new_layout))
    {
        button_layout = new_layout;
        emit_changed (META_PREF_BUTTON_LAYOUT);
    }

    return TRUE;
}