]> mj.ucw.cz Git - osdd.git/commitdiff
New display code is able to show text messages
authorMartin Mares <mj@ucw.cz>
Tue, 22 Oct 2013 20:54:41 +0000 (22:54 +0200)
committerMartin Mares <mj@ucw.cz>
Tue, 22 Oct 2013 20:54:41 +0000 (22:54 +0200)
Sliders and percentages are not implemented yet.
Line spacing and outline widths are configurable.
Undocumented test mode has been added.

display.c
display.h
osdd.c

index 1294db706868a7b542c264167b3e65f7fc29dab8..d2decdce1ebc27f473fe20d26ca51be841309eaa 100644 (file)
--- a/display.c
+++ b/display.c
@@ -53,6 +53,7 @@ struct osd_state {
   int max_lines;
   int line_distance;
   int line_height;
+  int line_skip;
   bool visible;
 };
 
@@ -71,7 +72,7 @@ stay_on_top(struct osd_state *osd)
       nitems > 0)
     {
       DBG("stay_on_top: Gnome mode\n");
-      // FIXME: check capabilities
+      // FIXME: Check capabilities
       XClientMessageEvent e;
       memset(&e, 0, sizeof(e));
       e.type = ClientMessage;
@@ -129,7 +130,7 @@ struct osd_state *osd_new(Display *dpy)
   if (!XShapeQueryExtension(osd->dpy, &event_basep, &error_basep))
     die("XShape extension not supported by X server, giving up");
 
-  osd->max_lines = 2;  // FIXME
+  osd->max_lines = 4;
   osd->lines = xmalloc(sizeof(struct osd_line) * osd->max_lines);
 
   return osd;
@@ -146,19 +147,21 @@ void osd_free(struct osd_state *osd)
   free(osd);
 }
 
-void osd_set_font(struct osd_state *osd, char *font_name)
+void osd_set_font(struct osd_state *osd, char *font_name, double line_spacing)
 {
   if (osd->font)
     XftFontClose(osd->dpy, osd->font);
 
-  DBG("Using font %s", font_name);
+  DBG("Using font %s\n", font_name);
   osd->font = XftFontOpenName(osd->dpy, osd->screen, font_name);
   if (!osd->font)
     die("Cannot open font %s", font_name);
-  DBG("Font: asc=%d desc=%d ht=%d", osd->font->ascent, osd->font->descent, osd->font->height);
+  DBG("Font: asc=%d desc=%d ht=%d\n", osd->font->ascent, osd->font->descent, osd->font->height);
 
   osd->line_distance = osd->font->height;
   osd->line_height = osd->font->ascent;
+  osd->line_skip = osd->line_distance * line_spacing;
+  DBG("Line: distance=%d height=%d skip=%d\n", osd->line_distance, osd->line_height, osd->line_skip);
 }
 
 struct osd_line *osd_add_line(struct osd_state *osd, enum osd_line_type type)
@@ -172,9 +175,8 @@ struct osd_line *osd_add_line(struct osd_state *osd, enum osd_line_type type)
   struct osd_line *l = &osd->lines[osd->num_lines++];
   l->type = type;
   l->fg_color = "green";
-  l->outline_color = "yellow";
+  l->outline_color = "black";
   l->outline_width = 0;
-  // FIXME: Colors, alignment etc.
 
   switch (l->type)
     {
@@ -228,9 +230,10 @@ static void osd_prepare(struct osd_state *osd)
       if (line->width > osd->win_width)
        osd->win_width = line->width;
       osd->win_height += line->height;
+      if (i)
+       osd->win_height += osd->line_skip;
     }
 
-  // FIXME: Check clipping
   if (osd->win_width > osd->screen_width)
     osd->win_width = osd->screen_width;
   if (osd->win_height > osd->screen_height)
@@ -241,6 +244,8 @@ static void osd_prepare(struct osd_state *osd)
   for (int i=0; i < osd->num_lines; i++)
     {
       struct osd_line *line = &osd->lines[i];
+      if (i)
+       y += osd->line_skip;
       line->y_pos = y;
       osd_justify_line(osd, i);
       y += line->height;
@@ -266,16 +271,19 @@ static void osd_draw_line(struct osd_state *osd, int i)
     {
     case OSD_TYPE_TEXT:
       {
+       int x = line->x_pos + line->outline_width;
+       int y = line->y_pos + line->outline_width + osd->line_height;
+
        unsigned char *text = (unsigned char *) line->u.text;
        int text_len = strlen(line->u.text);
-       XftDrawStringUtf8(osd->image_draw, &fg_color, osd->font, line->x_pos + line->outline_width, line->y_pos + line->outline_width, text, text_len);
+       XftDrawStringUtf8(osd->image_draw, &fg_color, osd->font, x, y, text, text_len);
 
        // This is slow, but unlike the method used by libxosd, the result isn't ugly.
        int outline = line->outline_width;
        for (int dx = -outline; dx <= outline; dx++)
          for (int dy = -outline; dy <= outline; dy++)
            if (dx*dx + dy*dy <= outline*outline)
-             XftDrawStringUtf8(osd->mask_draw, &mask_color, osd->font, 100 + dx, 100 + dy, text, text_len);
+             XftDrawStringUtf8(osd->mask_draw, &mask_color, osd->font, x + dx, y + dy, text, text_len);
 
        break;
       }
@@ -299,7 +307,7 @@ void osd_show(struct osd_state *osd)
   };
   osd->win = XCreateWindow(osd->dpy,
        osd->root,
-       0, 0,
+       (osd->screen_width - osd->win_width) / 2, (osd->screen_height - osd->win_height) / 2,
        osd->win_width, osd->win_height,
        0,
        osd->depth,
@@ -362,6 +370,12 @@ void osd_hide(struct osd_state *osd)
   osd->visible = 0;
 }
 
+void osd_clear(struct osd_state *osd)
+{
+  osd_hide(osd);
+  osd->num_lines = 0;
+}
+
 bool osd_handle_event(struct osd_state *osd, XEvent *ev)
 {
   if (!osd->visible)
index fba43dfa08eebbcc9f70ed208d39c9d03c9a791e..48ffb0be3783377ea26828d11e7d92bae0dd2d3f 100644 (file)
--- a/display.h
+++ b/display.h
@@ -26,6 +26,7 @@ struct osd_line {
     char text[OSD_MAX_LINE_LEN];               // in UTF-8
   } u;
 
+  // Used internally
   int width;
   int height;
   int x_pos;
@@ -34,8 +35,9 @@ struct osd_line {
 
 struct osd_state *osd_new(Display *dpy);
 void osd_free(struct osd_state *osd);
-void osd_set_font(struct osd_state *osd, char *font_name);
+void osd_set_font(struct osd_state *osd, char *font_name, double line_spacing);
 struct osd_line *osd_add_line(struct osd_state *osd, enum osd_line_type type);
 void osd_show(struct osd_state *osd);
 void osd_hide(struct osd_state *osd);
+void osd_clear(struct osd_state *osd);
 bool osd_handle_event(struct osd_state *osd, XEvent *ev);
diff --git a/osdd.c b/osdd.c
index 8626cbd8f96ea276a7a793e84937784bc271498c..2bfb8c35e60ec0baa5131f67925d5efa281411f9 100644 (file)
--- a/osdd.c
+++ b/osdd.c
@@ -25,24 +25,32 @@ static timestamp_t now;
 
 /*** Options ***/
 
-static int num_lines = 4;      // FIXME
-static char *font_name = "-bitstream-bitstream vera sans-bold-r-normal-*-*-320-*-*-p-*-*";     // FIXME
+static char *font_name = "times-64";
 static char *default_color = "green";
 static char *default_outline_color = "black";
+static int default_outline_width = 2;
 static int default_duration = 1000;
 static int default_min_duration = 250;
 static int debug_mode;
+static int test_mode;
+static double line_spacing = 0.2;
 
-static const char short_opts[] = "c:d:Df:l:m:o:";
+static const char short_opts[] = "c:d:Df:m:o:O:s:";
+
+enum long_opt {
+  OPT_TEST = 256,
+};
 
 static const struct option long_opts[] = {
   { "color",           required_argument,      NULL,   'c' },
   { "debug",           no_argument,            NULL,   'D' },
   { "duration",                required_argument,      NULL,   'd' },
   { "font",            required_argument,      NULL,   'f' },
-  { "lines",           required_argument,      NULL,   'l' },
   { "min-duration",    required_argument,      NULL,   'm' },
   { "outline-color",   required_argument,      NULL,   'o' },
+  { "outline-width",   required_argument,      NULL,   'O' },
+  { "line-spacing",    required_argument,      NULL,   's' },
+  { "test",            no_argument,            NULL,   OPT_TEST },     // Undocumented test mode
   { NULL,              0,                      NULL,   0   },
 };
 
@@ -55,9 +63,10 @@ Options:\n\
 -D, --debug\t\tDebugging mode (do not detach from the terminal)\n\
 -d, --duration=<ms>\tDefault message duration in milliseconds\n\
 -f, --font=<f>\t\tFont to use for the OSD\n\
--l, --lines=<n>\t\tNumber of lines of the OSD\n\
 -m, --min-duration=<ms>\tDefault minimum message duration in milliseconds\n\
 -o, --outline-color=<c>\tDefault outline color\n\
+-O, --outline-width=<n>\tDefault outline width (default=2)\n\
+-s, --line-spacing=<n>\tSet line spacing factor (decimal fraction, default=0.2)\n\
 ");
   exit(1);
 }
@@ -82,9 +91,7 @@ parse_opts(int argc, char **argv)
        font_name = optarg;
        break;
       case 'l':
-       num_lines = atoi(optarg);
-       if (num_lines < 1)
-         usage();
+       line_spacing = atof(optarg);
        break;
       case 'm':
        default_min_duration = atoi(optarg);
@@ -92,6 +99,13 @@ parse_opts(int argc, char **argv)
       case 'o':
        default_outline_color = optarg;
        break;
+      case 'O':
+       default_outline_width = atoi(optarg);
+       break;
+      case OPT_TEST:
+       test_mode = 1;
+       debug_mode = 1;
+       break;
       default:
        usage();
       }
@@ -116,6 +130,7 @@ display_msg(struct msg *msg)
   msg->max_light = now + default_duration;
   char *fg_color = default_color;
   char *outline_color = default_outline_color;
+  int outline_width = default_outline_width;
 
   char *line = msg->text;
   while (*line)
@@ -152,21 +167,24 @@ display_msg(struct msg *msg)
       else if (!strcmp(key, "slider"))
        {
          // FIXME
-         // xsd_display(osd, row++, XOSD_slider, atoi(val));
+         // xosd_display(osd, row++, XOSD_slider, atoi(val));
        }
       else if (!strcmp(key, "duration"))
        msg->max_light = now + atoi(val);
       else if (!strcmp(key, "min-duration"))
        msg->min_light = now + atoi(val);
       else if (!strcmp(key, "color"))
-       fg_color = val;                         // FIXME: Need copying!
+       fg_color = val;
       else if (!strcmp(key, "outline-color"))
-       outline_color = val;                    // FIXME: Need copying!
+       outline_color = val;
+      else if (!strcmp(key, "outline-width"))
+       outline_width = atoi(val);
 
       if (l)
        {
          l->fg_color = fg_color;
          l->outline_color = outline_color;
+         l->outline_width = outline_width;
        }
 
       line = nl;
@@ -174,14 +192,15 @@ display_msg(struct msg *msg)
 
   if (msg->min_light > msg->max_light)
     msg->min_light = msg->max_light;
+
+  osd_show(osd);
 }
 
 static void
 hide_msg(struct msg *msg)
 {
   DBG("## Hiding message\n");
-  osd_hide(osd);
-  // FIXME: Reset the osd state
+  osd_clear(osd);
   free(msg);
 }
 
@@ -227,6 +246,19 @@ parse_input(unsigned char *buf, int len)
     }
 }
 
+static void
+do_test(void)
+{
+  unsigned char buf[4096];
+  int len = 0;
+  int c;
+
+  while ((c = read(0, buf + len, 4096 - len)) > 0)
+    len += c;
+  if (len)
+    enqueue_msg(buf, len);
+}
+
 /*** Main loop ***/
 
 int
@@ -255,12 +287,20 @@ main(int argc, char **argv)
       setsid();
     }
 
-  XSelectInput(dpy, win, PropertyChangeMask);
-  XDeleteProperty(dpy, win, pty);
-  XFlush(dpy);
+  if (test_mode)
+    {
+      do_test();
+      pty = 0;
+    }
+  else
+    {
+      XSelectInput(dpy, win, PropertyChangeMask);
+      XDeleteProperty(dpy, win, pty);
+      XFlush(dpy);
+    }
 
   osd = osd_new(dpy);
-  osd_set_font(osd, font_name);
+  osd_set_font(osd, font_name, line_spacing);
 
   struct pollfd pfd = {
     .fd = ConnectionNumber(dpy),
@@ -291,6 +331,8 @@ main(int argc, char **argv)
              continue;
            }
        }
+      if (test_mode && !current_msg)
+       break;
 
       DBG("... waiting for %d ms\n", (int)(wait_until - now));
       poll(&pfd, 1, wait_until - now);