diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/boxes.c | 123 | ||||
| -rw-r--r-- | src/core/constraints.c | 6 | ||||
| -rw-r--r-- | src/core/display-private.h | 9 | ||||
| -rw-r--r-- | src/core/display.c | 23 | ||||
| -rw-r--r-- | src/core/frame.c | 6 | ||||
| -rw-r--r-- | src/core/keybindings.c | 43 | ||||
| -rw-r--r-- | src/core/screen-private.h | 2 | ||||
| -rw-r--r-- | src/core/screen.c | 36 | ||||
| -rw-r--r-- | src/core/testboxes.c | 8 | ||||
| -rw-r--r-- | src/core/window-private.h | 19 | ||||
| -rw-r--r-- | src/core/window.c | 166 | ||||
| -rw-r--r-- | src/core/workspace.c | 3 | ||||
| -rw-r--r-- | src/include/boxes.h | 3 | ||||
| -rw-r--r-- | src/include/common.h | 4 | ||||
| -rw-r--r-- | src/ui/theme-parser.c | 44 | ||||
| -rw-r--r-- | src/ui/theme.c | 63 | ||||
| -rw-r--r-- | src/ui/theme.h | 8 | 
17 files changed, 414 insertions, 152 deletions
| diff --git a/src/core/boxes.c b/src/core/boxes.c index 877fa458..93f7db44 100644 --- a/src/core/boxes.c +++ b/src/core/boxes.c @@ -1791,6 +1791,7 @@ meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,  GList*  meta_rectangle_find_nonintersected_xinerama_edges ( +                                    const MetaRectangle *screen_rect,                                      const GList         *xinerama_rects,                                      const GSList        *all_struts)  { @@ -1813,98 +1814,38 @@ meta_rectangle_find_nonintersected_xinerama_edges (    while (cur)      {        MetaRectangle *cur_rect = cur->data; -      const GList *compare = xinerama_rects; -      while (compare) +      MetaEdge *new_edge; +      if (BOX_LEFT(*cur_rect) != BOX_LEFT(*screen_rect))          { -          MetaRectangle *compare_rect = compare->data; - -          /* Check if cur might be horizontally adjacent to compare */ -          if (meta_rectangle_vert_overlap(cur_rect, compare_rect)) -            { -              MetaSide side_type; -              int y      = MAX (cur_rect->y, compare_rect->y); -              int height = MIN (BOX_BOTTOM (*cur_rect) - y, -                                BOX_BOTTOM (*compare_rect) - y); -              int width  = 0; -              int x; - -              if (BOX_LEFT (*cur_rect)  == BOX_RIGHT (*compare_rect)) -                { -                  /* compare_rect is to the left of cur_rect */ -                  x = BOX_LEFT (*cur_rect); -                  side_type = META_SIDE_LEFT; -                } -              else if (BOX_RIGHT (*cur_rect) == BOX_LEFT (*compare_rect)) -                { -                  /* compare_rect is to the right of cur_rect */ -                  x = BOX_RIGHT (*cur_rect); -                  side_type = META_SIDE_RIGHT; -                } -              else -                /* These rectangles aren't adjacent after all */ -                x = INT_MIN; - -              /* If the rectangles really are adjacent */ -              if (x != INT_MIN) -                { -                  /* We need a left edge for the xinerama on the right, and -                   * a right edge for the xinerama on the left.  Just fill -                   * up the edges and stick 'em on the list. -                   */ -                  MetaEdge *new_edge  = g_new (MetaEdge, 1); - -                  new_edge->rect = meta_rect (x, y, width, height); -                  new_edge->side_type = side_type; -                  new_edge->edge_type = META_EDGE_XINERAMA; - -                  ret = g_list_prepend (ret, new_edge); -                } -            } - -          /* Check if cur might be vertically adjacent to compare */ -          if (meta_rectangle_horiz_overlap(cur_rect, compare_rect)) -            { -              MetaSide side_type; -              int x      = MAX (cur_rect->x, compare_rect->x); -              int width  = MIN (BOX_RIGHT (*cur_rect) - x, -                                BOX_RIGHT (*compare_rect) - x); -              int height = 0; -              int y; - -              if (BOX_TOP (*cur_rect)  == BOX_BOTTOM (*compare_rect)) -                { -                  /* compare_rect is to the top of cur_rect */ -                  y = BOX_TOP (*cur_rect); -                  side_type = META_SIDE_TOP; -                } -              else if (BOX_BOTTOM (*cur_rect) == BOX_TOP (*compare_rect)) -                { -                  /* compare_rect is to the bottom of cur_rect */ -                  y = BOX_BOTTOM (*cur_rect); -                  side_type = META_SIDE_BOTTOM; -                } -              else -                /* These rectangles aren't adjacent after all */ -                y = INT_MIN; - -              /* If the rectangles really are adjacent */ -              if (y != INT_MIN) -                { -                  /* We need a top edge for the xinerama on the bottom, and -                   * a bottom edge for the xinerama on the top.  Just fill -                   * up the edges and stick 'em on the list. -                   */ -                  MetaEdge *new_edge = g_new (MetaEdge, 1); - -                  new_edge->rect = meta_rect (x, y, width, height); -                  new_edge->side_type = side_type; -                  new_edge->edge_type = META_EDGE_XINERAMA; - -                  ret = g_list_prepend (ret, new_edge); -                } -            } - -          compare = compare->next; +          new_edge  = g_new (MetaEdge, 1); +          new_edge->rect = meta_rect (BOX_LEFT (*cur_rect), BOX_TOP (*cur_rect), 0, cur_rect->height); +          new_edge->side_type = META_SIDE_LEFT; +          new_edge->edge_type = META_EDGE_XINERAMA; +          ret = g_list_prepend (ret, new_edge); +        } +      if (BOX_RIGHT(*cur_rect) != BOX_RIGHT(*screen_rect)) +        { +          new_edge  = g_new (MetaEdge, 1); +          new_edge->rect = meta_rect (BOX_RIGHT (*cur_rect), BOX_TOP (*cur_rect), 0, cur_rect->height); +          new_edge->side_type = META_SIDE_RIGHT; +          new_edge->edge_type = META_EDGE_XINERAMA; +          ret = g_list_prepend (ret, new_edge); +        } +      if (BOX_TOP(*cur_rect) != BOX_TOP(*screen_rect)) +        { +          new_edge  = g_new (MetaEdge, 1); +          new_edge->rect = meta_rect (BOX_LEFT (*cur_rect), BOX_TOP (*cur_rect), cur_rect->width, 0); +          new_edge->side_type = META_SIDE_TOP; +          new_edge->edge_type = META_EDGE_XINERAMA; +          ret = g_list_prepend (ret, new_edge); +        } +      if (BOX_BOTTOM(*cur_rect) != BOX_BOTTOM(*screen_rect)) +        { +          new_edge  = g_new (MetaEdge, 1); +          new_edge->rect = meta_rect (BOX_LEFT (*cur_rect), BOX_BOTTOM (*cur_rect), cur_rect->width, 0); +          new_edge->side_type = META_SIDE_BOTTOM; +          new_edge->edge_type = META_EDGE_XINERAMA; +          ret = g_list_prepend (ret, new_edge);          }        cur = cur->next;      } diff --git a/src/core/constraints.c b/src/core/constraints.c index 68cf5ae1..656d1529 100644 --- a/src/core/constraints.c +++ b/src/core/constraints.c @@ -748,8 +748,10 @@ constrain_maximization (MetaWindow         *window,      return TRUE;    /* Calculate target_size = maximized size of (window + frame) */ -  if (window->maximized_horizontally && window->maximized_vertically) -    target_size = info->work_area_xinerama; +  if (META_WINDOW_MAXIMIZED (window)) +    { +      target_size = info->work_area_xinerama; +    }    else      {        /* Amount of maximization possible in a single direction depends diff --git a/src/core/display-private.h b/src/core/display-private.h index d8842a3e..dc270a96 100644 --- a/src/core/display-private.h +++ b/src/core/display-private.h @@ -67,6 +67,13 @@ typedef void (*MetaWindowPingFunc) (MetaDisplay* display, Window xwindow, guint3   */  #define N_IGNORED_SERIALS           4 +typedef enum { +  META_TILE_NONE, +  META_TILE_LEFT, +  META_TILE_RIGHT, +  META_TILE_MAXIMIZED /* only used for previews */ +} MetaTileMode; +  struct _MetaDisplay {  	char* name;  	Display* xdisplay; @@ -155,6 +162,8 @@ struct _MetaDisplay {  	int         grab_anchor_root_x;  	int         grab_anchor_root_y;  	MetaRectangle grab_anchor_window_pos; +	MetaTileMode  grab_tile_mode; +	int           grab_tile_monitor_number;  	int         grab_latest_motion_x;  	int         grab_latest_motion_y;  	gulong      grab_mask; diff --git a/src/core/display.c b/src/core/display.c index e12dd60a..76408930 100644 --- a/src/core/display.c +++ b/src/core/display.c @@ -465,6 +465,8 @@ meta_display_open (void)    the_display->grab_window = NULL;    the_display->grab_screen = NULL;    the_display->grab_resize_popup = NULL; +  the_display->grab_tile_mode = META_TILE_NONE; +  the_display->grab_tile_monitor_number = -1;    the_display->grab_edge_resistance_data = NULL; @@ -3527,6 +3529,16 @@ meta_display_begin_grab_op (MetaDisplay *display,    display->grab_xwindow = grab_xwindow;    display->grab_button = button;    display->grab_mask = modmask; +  if (window) +    { +      display->grab_tile_mode = window->tile_mode; +      display->grab_tile_monitor_number = window->tile_monitor_number; +    } +  else +    { +      display->grab_tile_mode = META_TILE_NONE; +      display->grab_tile_monitor_number = -1; +    }    display->grab_anchor_root_x = root_x;    display->grab_anchor_root_y = root_y;    display->grab_latest_motion_x = root_x; @@ -3724,6 +3736,11 @@ meta_display_end_grab_op (MetaDisplay *display,    if (display->grab_window != NULL)      display->grab_window->shaken_loose = FALSE; +  /*if(display->grab_window != NULL && display->grab_window->tile_mode == META_TILE_MAXIMIZED) +    { +      display->grab_window->tile_mode = META_TILE_NONE; +    }*/ +    if (display->grab_window != NULL &&        !meta_prefs_get_raise_on_click () &&        (meta_grab_op_is_moving (display->grab_op) || @@ -3826,9 +3843,15 @@ meta_display_end_grab_op (MetaDisplay *display,      }  #endif /* HAVE_XSYNC */ +  /* Hide the tile preview if it exists */ +  if (display->grab_screen->tile_preview) +    meta_tile_preview_hide (display->grab_screen->tile_preview); +    display->grab_window = NULL;    display->grab_screen = NULL;    display->grab_xwindow = None; +  display->grab_tile_mode = META_TILE_NONE; +  display->grab_tile_monitor_number = -1;    display->grab_op = META_GRAB_OP_NONE;    if (display->grab_resize_popup) diff --git a/src/core/frame.c b/src/core/frame.c index 68af4b52..cabfefcd 100644 --- a/src/core/frame.c +++ b/src/core/frame.c @@ -282,6 +282,12 @@ meta_frame_get_flags (MetaFrame *frame)    if (META_WINDOW_MAXIMIZED (frame->window))      flags |= META_FRAME_MAXIMIZED; +  if (META_WINDOW_TILED_LEFT (frame->window)) +    flags |= META_FRAME_TILED_LEFT; + +  if (META_WINDOW_TILED_RIGHT (frame->window)) +    flags |= META_FRAME_TILED_RIGHT; +    if (frame->window->fullscreen)      flags |= META_FRAME_FULLSCREEN; diff --git a/src/core/keybindings.c b/src/core/keybindings.c index 83dc4f93..8176b96f 100644 --- a/src/core/keybindings.c +++ b/src/core/keybindings.c @@ -1394,6 +1394,10 @@ process_mouse_move_resize_grab (MetaDisplay *display,    if (keysym == XK_Escape)      { +      /* Restore the original tile mode */ +      window->tile_mode = display->grab_tile_mode; +      window->tile_monitor_number = display->grab_tile_monitor_number; +        /* End move or resize and restore to original state.  If the         * window was a maximized window that had been "shaken loose" we         * need to remaximize it.  In normal cases, we need to do a @@ -1405,6 +1409,8 @@ process_mouse_move_resize_grab (MetaDisplay *display,          meta_window_maximize (window,                                META_MAXIMIZE_HORIZONTAL |                                META_MAXIMIZE_VERTICAL); +      else if (window->tile_mode == META_TILE_LEFT || window->tile_mode == META_TILE_RIGHT) +        meta_window_tile (window);        else if (!display->grab_wireframe_active)          meta_window_move_resize (display->grab_window,                                   TRUE, @@ -3016,6 +3022,43 @@ handle_toggle_above       (MetaDisplay    *display,      meta_window_make_above (window);  } +/* TODO: actually use this keybinding, without messing up the existing keybinding schema */ +static void +handle_toggle_tiled (MetaDisplay *display, +                     MetaScreen *screen, +                     MetaWindow *window, +                     XEvent *event, +                     MetaKeyBinding *binding) +{ +  MetaTileMode mode = binding->handler->data; + +  if ((META_WINDOW_TILED_LEFT (window) && mode == META_TILE_LEFT) || +      (META_WINDOW_TILED_RIGHT (window) && mode == META_TILE_RIGHT)) +    { +      window->tile_mode = META_TILE_NONE; + +      if (window->saved_maximize) +        meta_window_maximize (window, META_MAXIMIZE_VERTICAL | +                                      META_MAXIMIZE_HORIZONTAL); +      else +        meta_window_unmaximize (window, META_MAXIMIZE_VERTICAL | +                                        META_MAXIMIZE_HORIZONTAL); +    } +  else if (meta_window_can_tile (window)) +    { +      window->tile_mode = mode; +      window->tile_monitor_number = meta_screen_get_xinerama_for_window (window->screen, window)->number; +      /* Maximization constraints beat tiling constraints, so if the window +       * is maximized, tiling won't have any effect unless we unmaximize it +       * horizontally first; rather than calling meta_window_unmaximize(), +       * we just set the flag and rely on meta_window_tile() syncing it to +       * save an additional roundtrip. +       */ +      window->maximized_horizontally = FALSE; +      meta_window_tile (window); +    } +} +  static void  handle_toggle_maximized    (MetaDisplay    *display,                             MetaScreen     *screen, diff --git a/src/core/screen-private.h b/src/core/screen-private.h index c2114144..6784cc9b 100644 --- a/src/core/screen-private.h +++ b/src/core/screen-private.h @@ -169,6 +169,8 @@ void          meta_screen_ensure_workspace_popup (MetaScreen *screen);  void          meta_screen_tile_preview_update          (MetaScreen    *screen,                                                          gboolean       delay); +void          meta_screen_tile_preview_hide            (MetaScreen    *screen); +  MetaWindow*   meta_screen_get_mouse_window     (MetaScreen                 *screen,                                                  MetaWindow                 *not_this_one); diff --git a/src/core/screen.c b/src/core/screen.c index 998bd6e4..bd3667e8 100644 --- a/src/core/screen.c +++ b/src/core/screen.c @@ -1476,6 +1476,7 @@ meta_screen_tile_preview_update_timeout (gpointer data)    MetaScreen *screen = data;    MetaWindow *window = screen->display->grab_window;    gboolean composited = screen->display->compositor != NULL; +  gboolean needs_preview = FALSE;    screen->tile_preview_timeout_id = 0; @@ -1483,9 +1484,28 @@ meta_screen_tile_preview_update_timeout (gpointer data)      screen->tile_preview = meta_tile_preview_new (screen->number,                                                    composited); -  if (window -      && !META_WINDOW_TILED (window) -      && window->tile_mode != META_TILE_NONE) +  if (window) +    { +      switch (window->tile_mode) +        { +          case META_TILE_LEFT: +          case META_TILE_RIGHT: +              if (!META_WINDOW_TILED (window)) +                needs_preview = TRUE; +              break; + +          case META_TILE_MAXIMIZED: +              if (!META_WINDOW_MAXIMIZED (window)) +                needs_preview = TRUE; +              break; + +          default: +              needs_preview = FALSE; +              break; +        } +    } + +  if (needs_preview)      {        MetaRectangle tile_rect; @@ -1523,6 +1543,16 @@ meta_screen_tile_preview_update (MetaScreen *screen,      }  } +void +meta_screen_tile_preview_hide (MetaScreen *screen) +{ +  if (screen->tile_preview_timeout_id > 0) +    g_source_remove (screen->tile_preview_timeout_id); + +  if (screen->tile_preview) +    meta_tile_preview_hide (screen->tile_preview); +} +  MetaWindow*  meta_screen_get_mouse_window (MetaScreen  *screen,                                MetaWindow  *not_this_one) diff --git a/src/core/testboxes.c b/src/core/testboxes.c index fda9795b..dfd65c69 100644 --- a/src/core/testboxes.c +++ b/src/core/testboxes.c @@ -347,8 +347,14 @@ get_xinerama_edges (int which_xinerama_set, int which_strut_set)    ret = NULL; +  MetaRectangle screenrect; +  screenrect.x = 0; +  screenrect.y = 0; +  screenrect.width = 1600; +  screenrect.height = 1200; +    struts = get_strut_list (which_strut_set); -  ret = meta_rectangle_find_nonintersected_xinerama_edges (xins, struts); +  ret = meta_rectangle_find_nonintersected_xinerama_edges (&screenrect, xins, struts);    free_strut_list (struts);    meta_rectangle_free_list_and_elements (xins); diff --git a/src/core/window-private.h b/src/core/window-private.h index 882c8901..20e619cb 100644 --- a/src/core/window-private.h +++ b/src/core/window-private.h @@ -84,13 +84,6 @@ typedef enum {  #define NUMBER_OF_QUEUES 3 -typedef enum { -  META_TILE_NONE, -  META_TILE_LEFT, -  META_TILE_RIGHT, -  META_TILE_MAXIMIZE -} MetaTileMode; -  struct _MetaWindow  {    MetaDisplay *display; @@ -151,6 +144,11 @@ struct _MetaWindow     * requested after the window grab is released */    guint tile_mode : 2; +  /* The last "full" maximized/unmaximized state. We need to keep track of +   * that to toggle between normal/tiled or maximized/tiled states. */ +  guint saved_maximize : 1; +  int tile_monitor_number; +    /* Whether we're shaded */    guint shaded : 1; @@ -405,6 +403,10 @@ struct _MetaWindow  #define META_WINDOW_TILED(w)           ((w)->maximized_vertically && \                                          !(w)->maximized_horizontally && \                                          (w)->tile_mode != META_TILE_NONE) +#define META_WINDOW_TILED_LEFT(w) (META_WINDOW_TILED(w) && \ +                                   (w)->tile_mode == META_TILE_LEFT) +#define META_WINDOW_TILED_RIGHT(w) (META_WINDOW_TILED(w) && \ +                                    (w)->tile_mode == META_TILE_RIGHT)  #define META_WINDOW_ALLOWS_MOVE(w)     ((w)->has_move_func && !(w)->fullscreen)  #define META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS(w)   ((w)->has_resize_func && !META_WINDOW_MAXIMIZED (w) && !META_WINDOW_TILED(w) && !(w)->fullscreen && !(w)->shaded)  #define META_WINDOW_ALLOWS_RESIZE(w)   (META_WINDOW_ALLOWS_RESIZE_EXCEPT_HINTS (w) &&                \ @@ -425,6 +427,7 @@ void        meta_window_free               (MetaWindow  *window,  void        meta_window_calc_showing       (MetaWindow  *window);  void        meta_window_queue              (MetaWindow  *window,                                              guint queuebits); +void        meta_window_tile               (MetaWindow  *window);  void        meta_window_minimize           (MetaWindow  *window);  void        meta_window_unminimize         (MetaWindow  *window);  void        meta_window_maximize           (MetaWindow        *window, @@ -663,4 +666,6 @@ gboolean meta_window_is_client_decorated (MetaWindow *window);  void meta_window_update_role (MetaWindow *window);  void meta_window_update_net_wm_type (MetaWindow *window); +gboolean meta_window_can_tile (MetaWindow *window); +  #endif diff --git a/src/core/window.c b/src/core/window.c index b0e69548..a811d668 100644 --- a/src/core/window.c +++ b/src/core/window.c @@ -471,6 +471,7 @@ meta_window_new_with_attrs (MetaDisplay       *display,    window->require_titlebar_visible = TRUE;    window->on_all_workspaces = FALSE;    window->tile_mode = META_TILE_NONE; +  window->tile_monitor_number = -1;    window->shaded = FALSE;    window->initially_iconic = FALSE;    window->minimized = FALSE; @@ -2612,6 +2613,9 @@ meta_window_maximize_internal (MetaWindow        *window,    else      meta_window_save_rect (window); +  if (maximize_horizontally && maximize_vertically) +    window->saved_maximize = TRUE; +    window->maximized_horizontally =      window->maximized_horizontally || maximize_horizontally;    window->maximized_vertically = @@ -2660,13 +2664,15 @@ meta_window_maximize (MetaWindow        *window,         */        if (!window->placed)  	{ -	  window->maximize_horizontally_after_placement = -            window->maximize_horizontally_after_placement || -            maximize_horizontally; -	  window->maximize_vertically_after_placement = -            window->maximize_vertically_after_placement || -            maximize_vertically; -	  return; +          window->maximize_horizontally_after_placement = window->maximize_horizontally_after_placement || maximize_horizontally; +          window->maximize_vertically_after_placement = window->maximize_vertically_after_placement || maximize_vertically; +          return; +        } + +      if (window->tile_mode != META_TILE_NONE) +        { +          saved_rect = &window->saved_rect; +          window->maximized_vertically = FALSE;  	}        if (window->tile_mode != META_TILE_NONE) @@ -2720,7 +2726,7 @@ unmaximize_window_before_freeing (MetaWindow        *window)      }  } -static void +void  meta_window_tile (MetaWindow *window)  {    /* Don't do anything if no tiling is requested */ @@ -2728,7 +2734,6 @@ meta_window_tile (MetaWindow *window)      return;    meta_window_maximize_internal (window, META_MAXIMIZE_VERTICAL, NULL); -  meta_screen_tile_preview_update (window->screen, FALSE);    /* move_resize with new tiling constraints     */ @@ -2736,11 +2741,18 @@ meta_window_tile (MetaWindow *window)  }  static gboolean +meta_window_can_tile_maximized (MetaWindow *window) +{ +  return window->has_maximize_func; +} + +gboolean  meta_window_can_tile (MetaWindow *window)  {    const MetaXineramaScreenInfo *monitor;    MetaRectangle tile_area; +  /*if (!META_WINDOW_ALLOWS_RESIZE (window))*/    if (!META_WINDOW_ALLOWS_RESIZE (window))      return FALSE; @@ -2771,7 +2783,8 @@ meta_window_unmaximize (MetaWindow        *window,    gboolean unmaximize_horizontally, unmaximize_vertically;    /* Restore tiling if necessary */ -  if (window->tile_mode != META_TILE_NONE) +  if (window->tile_mode == META_TILE_LEFT || +      window->tile_mode == META_TILE_RIGHT)      {        window->maximized_horizontally = FALSE;        meta_window_tile (window); @@ -2782,6 +2795,9 @@ meta_window_unmaximize (MetaWindow        *window,    unmaximize_vertically   = directions & META_MAXIMIZE_VERTICAL;    g_assert (unmaximize_horizontally || unmaximize_vertically); +  if (unmaximize_horizontally && unmaximize_vertically) +    window->saved_maximize = FALSE; +    /* Only do something if the window isn't already maximized in the     * given direction(s).     */ @@ -7019,35 +7035,56 @@ update_move (MetaWindow  *window,      DRAG_THRESHOLD_TO_SHAKE_THRESHOLD_FACTOR; -  if (meta_prefs_get_side_by_side_tiling () && -      meta_window_can_tile (window)) +  if (snap) +    { +      /* We don't want to tile while snapping. Also, clear any previous tile +         request. */ +      window->tile_mode = META_TILE_NONE; +      window->tile_monitor_number = -1; +    } +  else if (meta_prefs_get_side_by_side_tiling () && +           !META_WINDOW_MAXIMIZED (window) && +           !META_WINDOW_TILED (window))      {        const MetaXineramaScreenInfo *monitor;        MetaRectangle work_area; -      /* For tiling we are interested in the work area of the monitor where -       * the pointer is located. -       * Also see comment in meta_window_get_current_tile_area() +      /* For side-by-side tiling we are interested in the inside vertical +       * edges of the work area of the monitor where the pointer is located, +       * and in the outside top edge for maximized tiling. +       * +       * For maximized tiling we use the outside edge instead of the +       * inside edge, because we don't want to force users to maximize +       * windows they are placing near the top of their screens. +       * +       * The "current" idea of meta_window_get_work_area_current_monitor() and +       * meta_screen_get_current_monitor() is slightly different: the former +       * refers to the monitor which contains the largest part of the window, +       * the latter to the one where the pointer is located.         */        monitor = meta_screen_get_current_xinerama (window->screen);        meta_window_get_work_area_for_xinerama (window,                                                monitor->number,                                                &work_area); -      if (y >= monitor->rect.y && -          y < (monitor->rect.y + monitor->rect.height)) -        { -          /* check if cursor is near an edge of the work area */ -          if (x >= monitor->rect.x && x < (work_area.x + shake_threshold)) -            window->tile_mode = META_TILE_LEFT; -          else if (x >= work_area.x + work_area.width - shake_threshold && -                   x < (monitor->rect.x + monitor->rect.width)) -            window->tile_mode = META_TILE_RIGHT; -          else if ((y >= monitor->rect.y) && (y < work_area.y + shake_threshold)) -            window->tile_mode = META_TILE_MAXIMIZE; -          else -            window->tile_mode = META_TILE_NONE; -        } +      /* Check if the cursor is in a position which triggers tiling +       * and set tile_mode accordingly. +       */ +      if (meta_window_can_tile (window) && +          x >= monitor->rect.x && x < (work_area.x + shake_threshold)) +        window->tile_mode = META_TILE_LEFT; +      else if (meta_window_can_tile (window) && +               x >= work_area.x + work_area.width - shake_threshold && +               x < (monitor->rect.x + monitor->rect.width)) +        window->tile_mode = META_TILE_RIGHT; +      else if (meta_window_can_tile_maximized (window) && +               y >= monitor->rect.y && y <= work_area.y) +        window->tile_mode = META_TILE_MAXIMIZED; +      else +        window->tile_mode = META_TILE_NONE; + +      if (window->tile_mode != META_TILE_NONE) +        window->tile_monitor_number = monitor->number;      }    /* shake loose (unmaximize) maximized or tiled window if dragged beyond @@ -7060,7 +7097,10 @@ update_move (MetaWindow  *window,      {        double prop; -      /* Shake loose */ +      /* Shake loose, so that the window snaps back to maximized +       * when dragged near the top; do not snap back if the window +       * was tiled. +       */        window->shaken_loose = META_WINDOW_MAXIMIZED (window);        window->tile_mode = META_TILE_NONE; @@ -7137,6 +7177,8 @@ update_move (MetaWindow  *window,                display->grab_anchor_root_y = y;                window->shaken_loose = FALSE; +	      window->tile_mode = META_TILE_NONE; +                meta_window_maximize (window,                                      META_MAXIMIZE_HORIZONTAL |                                      META_MAXIMIZE_VERTICAL); @@ -7507,6 +7549,19 @@ check_use_this_motion_notify (MetaWindow *window,      }  } +static void +update_tile_mode (MetaWindow *window) +{ +  switch (window->tile_mode) +    { +      case META_TILE_LEFT: +      case META_TILE_RIGHT: +          if (!META_WINDOW_TILED (window)) +              window->tile_mode = META_TILE_NONE; +          break; +    } +} +  void  meta_window_handle_mouse_grab_op_event (MetaWindow *window,                                          XEvent     *event) @@ -7575,11 +7630,17 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,          {            if (meta_grab_op_is_moving (window->display->grab_op))              { -              if (window->tile_mode != META_TILE_NONE) -                meta_window_tile (window); -              else if (window->tile_mode == META_TILE_MAXIMIZE) -                meta_window_maximize (window, META_MAXIMIZE_HORIZONTAL | META_MAXIMIZE_VERTICAL); -              else if (event->xbutton.root == window->screen->xroot) +              if (window->tile_mode == META_TILE_MAXIMIZED) +	        { +                  meta_window_maximize (window, META_MAXIMIZE_VERTICAL | +                                                META_MAXIMIZE_HORIZONTAL); +                  window->tile_mode = META_TILE_NONE; +		} +	      else if (window->tile_mode != META_TILE_NONE) +	        { +		  meta_window_tile (window); +		} +	      else if (event->xbutton.root == window->screen->xroot)                  update_move (window, event->xbutton.state & ShiftMask,                               event->xbutton.x_root, event->xbutton.y_root);              } @@ -7593,6 +7654,15 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window,                                 TRUE);  	      if (window->display->compositor)  		meta_compositor_set_updates (window->display->compositor, window, TRUE); + +              /* If a tiled window has been dragged free with a +               * mouse resize without snapping back to the tiled +               * state, it will end up with an inconsistent tile +               * mode on mouse release; cleaning the mode earlier +               * would break the ability to snap back to the tiled +               * state, so we wait until mouse release. +               */ +              update_tile_mode (window);              }          } @@ -7741,17 +7811,29 @@ void  meta_window_get_current_tile_area (MetaWindow    *window,                                     MetaRectangle *tile_area)  { -  const MetaXineramaScreenInfo *monitor; +  int tile_monitor_number;    g_return_if_fail (window->tile_mode != META_TILE_NONE); -  /* The definition of "current" of meta_window_get_work_area_current_xinerama() -   * and meta_screen_get_current_xinerama() is slightly different: the former -   * refers to the monitor which contains the largest part of the window, the -   * latter to the one where the pointer is located. +  /* I don't know how to detect monitor configuration changes, so I have to take into account that +   * tile_monitor_number might be invalid. If this happens, I replace it with whatever monitor +   * the window is currently on. This is usually the correct monitor anyway, only in some special +   * cases is the real monitor number actually required (e.g. the window is being moved with the mouse but +   * is still mostly on the wrong monitor).     */ -  monitor = meta_screen_get_current_xinerama (window->screen); -  meta_window_get_work_area_for_xinerama (window, monitor->number, tile_area); +  if (window->tile_monitor_number >= window->screen->n_xinerama_infos) +    { +      window->tile_monitor_number = meta_screen_get_xinerama_for_window (window->screen, window)->number; +    } + +  tile_monitor_number = window->tile_monitor_number; +  if (tile_monitor_number < 0) +    { +      meta_warning ("%s called with an invalid monitor number; using 0 instead\n", G_STRFUNC); +      tile_monitor_number = 0; +    } + +  meta_window_get_work_area_for_xinerama (window, tile_monitor_number, tile_area);    if (window->tile_mode == META_TILE_LEFT  ||        window->tile_mode == META_TILE_RIGHT) diff --git a/src/core/workspace.c b/src/core/workspace.c index ef7ee1dd..eb2db05a 100644 --- a/src/core/workspace.c +++ b/src/core/workspace.c @@ -741,8 +741,7 @@ ensure_work_areas_validated (MetaWorkspace *workspace)    for (i = 0; i < workspace->screen->n_xinerama_infos; i++)      tmp = g_list_prepend (tmp, &workspace->screen->xinerama_infos[i].rect);    workspace->xinerama_edges = -    meta_rectangle_find_nonintersected_xinerama_edges (tmp, -                                                       workspace->all_struts); +    meta_rectangle_find_nonintersected_xinerama_edges (&workspace->screen->rect, tmp, workspace->all_struts);    g_list_free (tmp);    /* We're all done, YAAY!  Record that everything has been validated. */ diff --git a/src/include/boxes.h b/src/include/boxes.h index 0e30b2a8..cf49fe62 100644 --- a/src/include/boxes.h +++ b/src/include/boxes.h @@ -284,7 +284,8 @@ GList* meta_rectangle_find_onscreen_edges (const MetaRectangle *basic_rect,   * struts.   */  GList* meta_rectangle_find_nonintersected_xinerama_edges ( -                                           const GList         *xinerama_rects, +                                           const MetaRectangle *screen_rect, +					   const GList         *xinerama_rects,                                             const GSList        *all_struts);  #endif /* META_BOXES_H */ diff --git a/src/include/common.h b/src/include/common.h index c72ed834..69755e24 100644 --- a/src/include/common.h +++ b/src/include/common.h @@ -47,7 +47,9 @@ typedef enum    META_FRAME_ALLOWS_MOVE              = 1 << 11,    META_FRAME_FULLSCREEN               = 1 << 12,    META_FRAME_IS_FLASHING              = 1 << 13, -  META_FRAME_ABOVE                    = 1 << 14 +  META_FRAME_ABOVE                    = 1 << 14, +  META_FRAME_TILED_LEFT               = 1 << 15, +  META_FRAME_TILED_RIGHT              = 1 << 16  } MetaFrameFlags;  typedef enum diff --git a/src/ui/theme-parser.c b/src/ui/theme-parser.c index c94e0e9a..dccb47ad 100644 --- a/src/ui/theme-parser.c +++ b/src/ui/theme-parser.c @@ -3136,6 +3136,28 @@ parse_style_set_element (GMarkupParseContext  *context,            meta_frame_style_ref (frame_style);            info->style_set->maximized_styles[frame_focus] = frame_style;            break; +        case META_FRAME_STATE_TILED_LEFT: +          if (info->style_set->tiled_left_styles[frame_focus]) +            { +              set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, +                         _("Style has already been specified for state %s focus %s"), +                         state, focus); +              return; +            } +          meta_frame_style_ref (frame_style); +          info->style_set->tiled_left_styles[frame_focus] = frame_style; +          break; +        case META_FRAME_STATE_TILED_RIGHT: +          if (info->style_set->tiled_right_styles[frame_focus]) +            { +              set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, +                         _("Style has already been specified for state %s focus %s"), +                         state, focus); +              return; +            } +          meta_frame_style_ref (frame_style); +          info->style_set->tiled_right_styles[frame_focus] = frame_style; +          break;          case META_FRAME_STATE_SHADED:            if (info->style_set->shaded_styles[frame_resize][frame_focus])              { @@ -3158,6 +3180,28 @@ parse_style_set_element (GMarkupParseContext  *context,            meta_frame_style_ref (frame_style);            info->style_set->maximized_and_shaded_styles[frame_focus] = frame_style;            break; +        case META_FRAME_STATE_TILED_LEFT_AND_SHADED: +          if (info->style_set->tiled_left_and_shaded_styles[frame_focus]) +            { +              set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, +                         _("Style has already been specified for state %s focus %s"), +                         state, focus); +              return; +            } +          meta_frame_style_ref (frame_style); +          info->style_set->tiled_left_and_shaded_styles[frame_focus] = frame_style; +          break; +        case META_FRAME_STATE_TILED_RIGHT_AND_SHADED: +          if (info->style_set->tiled_right_and_shaded_styles[frame_focus]) +            { +              set_error (error, context, G_MARKUP_ERROR, G_MARKUP_ERROR_PARSE, +                         _("Style has already been specified for state %s focus %s"), +                         state, focus); +              return; +            } +          meta_frame_style_ref (frame_style); +          info->style_set->tiled_right_and_shaded_styles[frame_focus] = frame_style; +          break;          case META_FRAME_STATE_LAST:            g_assert_not_reached ();            break; diff --git a/src/ui/theme.c b/src/ui/theme.c index aa49963a..763f4f3a 100644 --- a/src/ui/theme.c +++ b/src/ui/theme.c @@ -851,7 +851,9 @@ meta_frame_layout_calc_geometry (const MetaFrameLayout  *layout,        rect->visible.width = button_width;        rect->visible.height = button_height; -      if (flags & META_FRAME_MAXIMIZED) +      if (flags & META_FRAME_MAXIMIZED || +          flags & META_FRAME_TILED_LEFT || +	  flags & META_FRAME_TILED_RIGHT)          {            rect->clickable.x = rect->visible.x;            rect->clickable.y = rect->visible.y; @@ -4995,7 +4997,11 @@ meta_frame_style_set_unref (MetaFrameStyleSet *style_set)          }        free_focus_styles (style_set->maximized_styles); +      free_focus_styles (style_set->tiled_left_styles); +      free_focus_styles (style_set->tiled_right_styles);        free_focus_styles (style_set->maximized_and_shaded_styles); +      free_focus_styles (style_set->tiled_left_and_shaded_styles); +      free_focus_styles (style_set->tiled_right_and_shaded_styles);        if (style_set->parent)          meta_frame_style_set_unref (style_set->parent); @@ -5047,9 +5053,21 @@ get_style (MetaFrameStyleSet *style_set,            case META_FRAME_STATE_MAXIMIZED:              styles = style_set->maximized_styles;              break; +          case META_FRAME_STATE_TILED_LEFT: +            styles = style_set->tiled_left_styles; +            break; +          case META_FRAME_STATE_TILED_RIGHT: +            styles = style_set->tiled_right_styles; +            break;            case META_FRAME_STATE_MAXIMIZED_AND_SHADED:              styles = style_set->maximized_and_shaded_styles;              break; +          case META_FRAME_STATE_TILED_LEFT_AND_SHADED: +            styles = style_set->tiled_left_and_shaded_styles; +            break; +          case META_FRAME_STATE_TILED_RIGHT_AND_SHADED: +            styles = style_set->tiled_right_and_shaded_styles; +            break;            case META_FRAME_STATE_NORMAL:            case META_FRAME_STATE_SHADED:            case META_FRAME_STATE_LAST: @@ -5059,6 +5077,19 @@ get_style (MetaFrameStyleSet *style_set,          style = styles[focus]; +        /* Tiled states are optional, try falling back to non-tiled states */ +        if (style == NULL) +          { +            if (state == META_FRAME_STATE_TILED_LEFT || +                state == META_FRAME_STATE_TILED_RIGHT) +              style = get_style (style_set, META_FRAME_STATE_NORMAL, +                                 resize, focus); +            else if (state == META_FRAME_STATE_TILED_LEFT_AND_SHADED || +                     state == META_FRAME_STATE_TILED_RIGHT_AND_SHADED) +              style = get_style (style_set, META_FRAME_STATE_SHADED, +                                 resize, focus); +          } +          /* Try parent if we failed here */          if (style == NULL && style_set->parent)            style = get_style (style_set->parent, state, resize, focus); @@ -5404,7 +5435,7 @@ theme_get_style (MetaTheme     *theme,    if (style_set == NULL)      return NULL; -  switch (flags & (META_FRAME_MAXIMIZED | META_FRAME_SHADED)) +  switch (flags & (META_FRAME_MAXIMIZED | META_FRAME_SHADED | META_FRAME_TILED_LEFT | META_FRAME_TILED_RIGHT))      {      case 0:        state = META_FRAME_STATE_NORMAL; @@ -5412,12 +5443,24 @@ theme_get_style (MetaTheme     *theme,      case META_FRAME_MAXIMIZED:        state = META_FRAME_STATE_MAXIMIZED;        break; +    case META_FRAME_TILED_LEFT: +      state = META_FRAME_STATE_TILED_LEFT; +      break; +    case META_FRAME_TILED_RIGHT: +      state = META_FRAME_STATE_TILED_RIGHT; +      break;      case META_FRAME_SHADED:        state = META_FRAME_STATE_SHADED;        break;      case (META_FRAME_MAXIMIZED | META_FRAME_SHADED):        state = META_FRAME_STATE_MAXIMIZED_AND_SHADED;        break; +    case (META_FRAME_TILED_LEFT | META_FRAME_SHADED): +      state = META_FRAME_STATE_TILED_LEFT_AND_SHADED; +      break; +    case (META_FRAME_TILED_RIGHT | META_FRAME_SHADED): +      state = META_FRAME_STATE_TILED_RIGHT_AND_SHADED; +      break;      default:        g_assert_not_reached ();        state = META_FRAME_STATE_LAST; /* compiler */ @@ -6264,10 +6307,18 @@ meta_frame_state_from_string (const char *str)      return META_FRAME_STATE_NORMAL;    else if (strcmp ("maximized", str) == 0)      return META_FRAME_STATE_MAXIMIZED; +  else if (strcmp ("tiled_left", str) == 0) +    return META_FRAME_STATE_TILED_LEFT; +  else if (strcmp ("tiled_right", str) == 0) +    return META_FRAME_STATE_TILED_RIGHT;    else if (strcmp ("shaded", str) == 0)      return META_FRAME_STATE_SHADED;    else if (strcmp ("maximized_and_shaded", str) == 0)      return META_FRAME_STATE_MAXIMIZED_AND_SHADED; +  else if (strcmp ("tiled_left_and_shaded", str) == 0) +    return META_FRAME_STATE_TILED_LEFT_AND_SHADED; +  else if (strcmp ("tiled_right_and_shaded", str) == 0) +    return META_FRAME_STATE_TILED_RIGHT_AND_SHADED;    else      return META_FRAME_STATE_LAST;  } @@ -6281,10 +6332,18 @@ meta_frame_state_to_string (MetaFrameState state)        return "normal";      case META_FRAME_STATE_MAXIMIZED:        return "maximized"; +    case META_FRAME_STATE_TILED_LEFT: +      return "tiled_left"; +    case META_FRAME_STATE_TILED_RIGHT: +      return "tiled_right";      case META_FRAME_STATE_SHADED:        return "shaded";      case META_FRAME_STATE_MAXIMIZED_AND_SHADED:        return "maximized_and_shaded"; +    case META_FRAME_STATE_TILED_LEFT_AND_SHADED: +      return "tiled_left_and_shaded"; +    case META_FRAME_STATE_TILED_RIGHT_AND_SHADED: +      return "tiled_right_and_shaded";      case META_FRAME_STATE_LAST:        break;      } diff --git a/src/ui/theme.h b/src/ui/theme.h index 89d41efe..c7437bdf 100644 --- a/src/ui/theme.h +++ b/src/ui/theme.h @@ -716,8 +716,12 @@ typedef enum  {    META_FRAME_STATE_NORMAL,    META_FRAME_STATE_MAXIMIZED, +  META_FRAME_STATE_TILED_LEFT, +  META_FRAME_STATE_TILED_RIGHT,    META_FRAME_STATE_SHADED,    META_FRAME_STATE_MAXIMIZED_AND_SHADED, +  META_FRAME_STATE_TILED_LEFT_AND_SHADED, +  META_FRAME_STATE_TILED_RIGHT_AND_SHADED,    META_FRAME_STATE_LAST  } MetaFrameState; @@ -754,8 +758,12 @@ struct _MetaFrameStyleSet    MetaFrameStyleSet *parent;    MetaFrameStyle *normal_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST];    MetaFrameStyle *maximized_styles[META_FRAME_FOCUS_LAST]; +  MetaFrameStyle *tiled_left_styles[META_FRAME_FOCUS_LAST]; +  MetaFrameStyle *tiled_right_styles[META_FRAME_FOCUS_LAST];    MetaFrameStyle *shaded_styles[META_FRAME_RESIZE_LAST][META_FRAME_FOCUS_LAST];    MetaFrameStyle *maximized_and_shaded_styles[META_FRAME_FOCUS_LAST]; +  MetaFrameStyle *tiled_left_and_shaded_styles[META_FRAME_FOCUS_LAST]; +  MetaFrameStyle *tiled_right_and_shaded_styles[META_FRAME_FOCUS_LAST];  };  /** | 
