]> git.eshelyaron.com Git - emacs.git/commitdiff
Improve window dividers code.
authorMartin Rudalics <rudalics@gmx.at>
Tue, 4 Feb 2014 07:36:58 +0000 (08:36 +0100)
committerMartin Rudalics <rudalics@gmx.at>
Tue, 4 Feb 2014 07:36:58 +0000 (08:36 +0100)
* faces.el (window-divider): New default value.  Rewrite
doc-string.
(window-divider-first-pixel, window-divider-last-pixel): New
faces.
* dispextern.h (face_id): Add WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID
and WINDOW_DIVIDER_LAST_PIXEL_FACE_ID.
* w32term.c (w32_draw_window_divider): Handle first and last
pixels specially.
* w32term.h (w32_fill_area_abs): New function.
* xdisp.c (x_draw_right_divider): Don't draw over bottom
divider.
* xfaces.c (realize_basic_faces): Handle new face ids.
* xfns.c (Fx_create_frame): Call x_default_parameter for right
and bottom divider width.
* xterm.c (x_draw_window_divider): Handle first and last pixels
specially.

etc/NEWS
lisp/ChangeLog
lisp/faces.el
src/ChangeLog
src/dispextern.h
src/w32term.c
src/w32term.h
src/xdisp.c
src/xfaces.c
src/xfns.c
src/xterm.c

index cfcb74cf782ba1778e3fb0f957656d604fc5b3a5..11cb240890a933b2e0a845f16af960eb28fe6afb 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -196,6 +196,18 @@ command `frame-configuration-to-register' still exists, but is unbound.
 *** New hooks `focus-in-hook', `focus-out-hook'.
 These are normal hooks run when an Emacs frame gains or loses input focus.
 
+---
+*** Emacs can now draw dividers between adjacent windows.  To put
+dividers between side-by-side windows customize the frame parameter
+right-divider-width to some positive integer.  To put dividers between
+vertically stacked windows set the frame parameter bottom-divider-width
+to some positive integer.  Dividers can be dragged with the mouse and
+show a corresponding cursor when the mouse hovers over them.  The
+appearance of dividers can be changed by customizing the basic faces
+window-divider, window-divider-first-pixel and window-divider-last-pixel
+where the latter two are useful to provide a 3D effect or to better set
+dividers apart from surrounding display objects.
+
 ---
 *** `split-window' is now a non-interactive function, not a command.
 As a command, it was a special case of `C-x 2' (`split-window-below'),
index 7c204726568204c3616271b666a3bc3d1e730e95..a97860c8aa613af4c5f4e3cacbb935931c1d93ff 100644 (file)
@@ -1,3 +1,10 @@
+2014-02-03  Martin Rudalics  <rudalics@gmx.at>
+
+       * faces.el (window-divider): New default value.  Rewrite
+       doc-string.
+       (window-divider-first-pixel, window-divider-last-pixel): New
+       faces.
+
 2014-02-03  Dmitry Gutov  <dgutov@yandex.ru>
 
        * progmodes/ruby-mode.el (ruby-font-lock-keywords): `private',
index aa9d25c31d71863d9aecb2a9a7c059c50482c14e..460fddf9ccd958693061a84eb47659d8dfe2c884 100644 (file)
@@ -2425,6 +2425,39 @@ Use the face `mode-line-highlight' for features that can be selected."
   :version "22.1"
   :group 'basic-faces)
 
+(defface window-divider '((t :foreground "gray60"))
+  "Basic face for window dividers.
+When a divider is less than 3 pixels wide, it is drawn solidly
+with the foreground of this face.  For larger dividers this face
+is used for the inner part while the first pixel line/column is
+drawn with the `window-divider-first-pixel' face and the last
+pixel line/column with the `window-divider-last-pixel' face."
+  :version "24.4"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface window-divider-first-pixel
+  '((t :foreground "gray80"))
+  "Basic face for first pixel line/column of window dividers.
+When a divider is at least 3 pixels wide, its first pixel
+line/column is drawn with the foreground of this face.  If you do
+not want to accentuate the first pixel line/column, set this to
+the same as `window-divider' face."
+  :version "24.4"
+  :group 'frames
+  :group 'basic-faces)
+
+(defface window-divider-last-pixel
+  '((t :foreground "gray40"))
+  "Basic face for last pixel line/column of window dividers.
+When a divider is at least 3 pixels wide, its last pixel
+line/column is drawn with the foreground of this face.  If you do
+not want to accentuate the last pixel line/column, set this to
+the same as `window-divider' face."
+  :version "24.4"
+  :group 'frames
+  :group 'basic-faces)
+
 (defface minibuffer-prompt
   '((((background dark)) :foreground "cyan")
     ;; Don't use blue because many users of the MS-DOS port customize
index ac41dabafcde72416498d92a4e6460ccddb8b833..ec003cd59b21b041b7bb104331bb6ab919e76cb6 100644 (file)
@@ -1,3 +1,18 @@
+2014-02-03  Martin Rudalics  <rudalics@gmx.at>
+
+       * dispextern.h (face_id): Add WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID
+       and WINDOW_DIVIDER_LAST_PIXEL_FACE_ID.
+       * w32term.c (w32_draw_window_divider): Handle first and last
+       pixels specially.
+       * w32term.h (w32_fill_area_abs): New function.
+       * xdisp.c (x_draw_right_divider): Don't draw over bottom
+       divider.
+       * xfaces.c (realize_basic_faces): Handle new face ids.
+       * xfns.c (Fx_create_frame): Call x_default_parameter for right
+       and bottom divider width.
+       * xterm.c (x_draw_window_divider): Handle first and last pixels
+       specially.
+
 2014-02-03  Dmitry Antipov  <dmantipov@yandex.ru>
 
        * print.c (Fexternal_debugging_output): Add cast to pacify
index a5dd054c123e13ba9914d5df1d2c846c3a517885..9ecd4ecdf7e26a3105031ab96ff80ab04b94d391 100644 (file)
@@ -1765,6 +1765,8 @@ enum face_id
   MENU_FACE_ID,
   VERTICAL_BORDER_FACE_ID,
   WINDOW_DIVIDER_FACE_ID,
+  WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID,
+  WINDOW_DIVIDER_LAST_PIXEL_FACE_ID,
   BASIC_FACE_ID_SENTINEL
 };
 
index 03d5a0047bc567f12e436d6424e135109b98f6e0..b77d01796d7d3636c2d474380e4c42520c231f4a 100644 (file)
@@ -628,26 +628,38 @@ static void
 w32_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  RECT r;
-  HDC hdc;
-  struct face *face;
-
-  r.left = x0;
-  r.right = x1;
-  r.top = y0;
-  r.bottom = y1;
-
-  hdc = get_frame_dc (f);
-  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
-  if (face)
-    w32_fill_rect (f, hdc, face->foreground, &r);
+  HDC hdc = get_frame_dc (f);
+  struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+  struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+  unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+  unsigned long color_first = (face_first
+                              ? face_first->foreground
+                              : FRAME_FOREGROUND_PIXEL (f));
+  unsigned long color_last = (face_last
+                             ? face_last->foreground
+                             : FRAME_FOREGROUND_PIXEL (f));
+
+  if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+    /* Vertical.  */
+    {
+      w32_fill_area_abs (f, hdc, color_first, x0, y0, x0 + 1, y1);
+      w32_fill_area_abs (f, hdc, color, x0 + 1, y0, x1 - 1, y1);
+      w32_fill_area_abs (f, hdc, color_last, x1 - 1, y0, x1, y1);
+    }
+  else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+    /* Horizontal.  */
+    {
+      w32_fill_area_abs (f, hdc, color_first, x0, y0, x1, y0 + 1);
+      w32_fill_area_abs (f, hdc, color, x0, y0 + 1, x1, y1 - 1);
+      w32_fill_area_abs (f, hdc, color_last, x0, y1 - 1, x1, y1);
+    }
   else
-    w32_fill_rect (f, hdc, FRAME_FOREGROUND_PIXEL (f), &r);
+    w32_fill_area_abs (f, hdc, color, x0, y0, x1, y1);
 
   release_frame_dc (f, hdc);
 }
 
-
 /* End update of window W.
 
    Draw vertical borders between horizontally adjacent windows, and
index 5a1ae283137b0bf660b6a252207fbb248e74cad6..f85e6bced8b53c49f9dfbe624fb038826dc79de0 100644 (file)
@@ -537,6 +537,16 @@ do { \
     w32_fill_rect (f,hdc,pix,&rect); \
 } while (0)
 
+#define w32_fill_area_abs(f,hdc,pix,x0,y0,x1,y1) \
+do { \
+    RECT rect; \
+    rect.left = x0; \
+    rect.top = y0; \
+    rect.right = x1; \
+    rect.bottom = y1; \
+    w32_fill_rect (f,hdc,pix,&rect); \
+} while (0)
+
 #define w32_clear_rect(f,hdc,lprect) \
   w32_fill_rect (f, hdc, FRAME_BACKGROUND_PIXEL (f), lprect)
 
index b5dec35568ae2faab672ceea92d281430a1027ab..0ca877d997f02d05038af4c0b6338b9d7fa5552c 100644 (file)
@@ -29277,7 +29277,8 @@ x_draw_right_divider (struct window *w)
       int x0 = WINDOW_RIGHT_EDGE_X (w) - WINDOW_RIGHT_DIVIDER_WIDTH (w);
       int x1 = WINDOW_RIGHT_EDGE_X (w);
       int y0 = WINDOW_TOP_EDGE_Y (w);
-      int y1 = WINDOW_BOTTOM_EDGE_Y (w);
+      /* The bottom divider prevails.  */
+      int y1 = WINDOW_BOTTOM_EDGE_Y (w) - WINDOW_BOTTOM_DIVIDER_WIDTH (w);
 
       FRAME_RIF (f)->draw_window_divider (w, x0, x1, y0, y1);
     }
index f2d777a12b17fdc53adef2d59f86ab295a04b4db..4271e47c36f8eb72cfed1295f4734ab7f8cf5583 100644 (file)
@@ -324,6 +324,8 @@ static Lisp_Object Qborder, Qmouse, Qmenu;
 Lisp_Object Qmode_line_inactive;
 static Lisp_Object Qvertical_border;
 static Lisp_Object Qwindow_divider;
+static Lisp_Object Qwindow_divider_first_pixel;
+static Lisp_Object Qwindow_divider_last_pixel;
 
 /* The symbol `face-alias'.  A symbols having that property is an
    alias for another face.  Value of the property is the name of
@@ -5249,6 +5251,10 @@ realize_basic_faces (struct frame *f)
       realize_named_face (f, Qmenu, MENU_FACE_ID);
       realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID);
       realize_named_face (f, Qwindow_divider, WINDOW_DIVIDER_FACE_ID);
+      realize_named_face (f, Qwindow_divider_first_pixel,
+                         WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+      realize_named_face (f, Qwindow_divider_last_pixel,
+                         WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
 
       /* Reflect changes in the `menu' face in menu bars.  */
       if (FRAME_FACE_CACHE (f)->menu_face_changed_p)
@@ -6452,6 +6458,8 @@ syms_of_xfaces (void)
   DEFSYM (Qmode_line_inactive, "mode-line-inactive");
   DEFSYM (Qvertical_border, "vertical-border");
   DEFSYM (Qwindow_divider, "window-divider");
+  DEFSYM (Qwindow_divider_first_pixel, "window-divider-first-pixel");
+  DEFSYM (Qwindow_divider_last_pixel, "window-divider-last-pixel");
   DEFSYM (Qtty_color_desc, "tty-color-desc");
   DEFSYM (Qtty_color_standard_values, "tty-color-standard-values");
   DEFSYM (Qtty_color_by_index, "tty-color-by-index");
index debc707dba28259a884166f52940598a6f1e908c..ff492dcf12612a091fcc7647b591b5fa02156101 100644 (file)
@@ -3033,6 +3033,10 @@ This function is an internal primitive--use `make-frame' instead.  */)
 #endif
                       "internalBorderWidth", "internalBorderWidth",
                       RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qright_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
+  x_default_parameter (f, parms, Qbottom_divider_width, make_number (0),
+                      NULL, NULL, RES_TYPE_NUMBER);
   x_default_parameter (f, parms, Qvertical_scroll_bars,
 #if defined (USE_GTK) && defined (USE_TOOLKIT_SCROLL_BARS)
                       Qright,
index 685fdf40a7008fc9ccb2ed6351653dec2fe0c877..e1873127276eb20e27dfc8f2d730c6ce0f79e200 100644 (file)
@@ -510,15 +510,51 @@ static void
 x_draw_window_divider (struct window *w, int x0, int x1, int y0, int y1)
 {
   struct frame *f = XFRAME (WINDOW_FRAME (w));
-  struct face *face;
-
-  face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
-  if (face)
-    XSetForeground (FRAME_X_DISPLAY (f), f->output_data.x->normal_gc,
-                   face->foreground);
+  struct face *face = FACE_FROM_ID (f, WINDOW_DIVIDER_FACE_ID);
+  struct face *face_first = FACE_FROM_ID (f, WINDOW_DIVIDER_FIRST_PIXEL_FACE_ID);
+  struct face *face_last = FACE_FROM_ID (f, WINDOW_DIVIDER_LAST_PIXEL_FACE_ID);
+  unsigned long color = face ? face->foreground : FRAME_FOREGROUND_PIXEL (f);
+  unsigned long color_first = (face_first
+                              ? face_first->foreground
+                              : FRAME_FOREGROUND_PIXEL (f));
+  unsigned long color_last = (face_last
+                             ? face_last->foreground
+                             : FRAME_FOREGROUND_PIXEL (f));
+  Display *display = FRAME_X_DISPLAY (f);
+  Window window = FRAME_X_WINDOW (f);
 
-  XFillRectangle (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
-                 f->output_data.x->normal_gc, x0, y0, x1 - x0, y1 - y0);
+  if (y1 - y0 > x1 - x0 && x1 - x0 > 2)
+    /* Vertical.  */
+    {
+      XSetForeground (display, f->output_data.x->normal_gc, color_first);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0, 1, y1 - y0);
+      XSetForeground (display, f->output_data.x->normal_gc, color);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0 + 1, y0, x1 - x0 - 2, y1 - y0);
+      XSetForeground (display, f->output_data.x->normal_gc, color_last);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x1 - 1, y0, 1, y1 - y0);
+    }
+  else if (x1 - x0 > y1 - y0 && y1 - y0 > 3)
+    /* Horizontal.  */
+    {
+      XSetForeground (display, f->output_data.x->normal_gc, color_first);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0, x1 - x0, 1);
+      XSetForeground (display, f->output_data.x->normal_gc, color);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0 + 1, x1 - x0, y1 - y0 - 2);
+      XSetForeground (display, f->output_data.x->normal_gc, color_last);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y1 - 1, x1 - x0, 1);
+    }
+  else
+    {
+      XSetForeground (display, f->output_data.x->normal_gc, color);
+      XFillRectangle (display, window, f->output_data.x->normal_gc,
+                     x0, y0, x1 - x0, y1 - y0);
+    }
 }
 
 /* End update of window W.