Two changes:
authorLuigi Rizzo <rizzo@icir.org>
Wed, 9 Jan 2008 18:03:40 +0000 (18:03 +0000)
committerLuigi Rizzo <rizzo@icir.org>
Wed, 9 Jan 2008 18:03:40 +0000 (18:03 +0000)
- support scrolling of message window;
- simplify the code for creating a message window,
  and try it using a second one in the top of
  the keypad (where we echo the dialed number).

The 'skin' that supports these two windows will be
committed separately.

git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@97530 65c4cc65-6c06-0410-ace0-fbb531ad65f3

channels/console_board.c
channels/console_gui.c
channels/console_video.h

index 9c913f8..f8805af 100644 (file)
@@ -44,8 +44,6 @@
 #ifdef HAVE_SDL        /* we only use this code if SDL is available */
 #include <SDL/SDL.h>
 
-#define GUI_BUFFER_LEN 256                     /* buffer lenght used for input buffers */
-
 /* Fonts characterization. XXX should be read from the file */
 #define FONT_H 20                      /* char height, pixels */
 #define FONT_W 9                       /* char width, pixels */
@@ -196,6 +194,17 @@ static void render_board(struct board *b)
        SDL_UpdateRects(b->screen, 1, b->p_rect);       /* Update the screen */
 }
 
+void move_message_board(struct board *b, int dy)
+{
+       int cur = b->cur_line + dy;
+       if (cur < 0)
+               cur = 0;
+       else if (cur >= b->v_h - b->p_h)
+               cur = b->v_h - b->p_h - 1;
+       b->cur_line = cur;
+       render_board(b);
+}
+
 /* return the content of a board */
 const char *read_message(const struct board *b)
 {
index 2bdbdf6..45e435f 100644 (file)
@@ -73,31 +73,10 @@ struct display_window   {
        SDL_Overlay     *bmp;
        SDL_Rect        rect;   /* location of the window */
 };
-#define GUI_BUFFER_LEN 256                     /* buffer lenght used for input buffers */
-
-/* Where do we send the keyboard/keypad output */
-enum kb_output {
-       KO_NONE,
-       KO_INPUT,       /* the local input window */
-       KO_DIALED,      /* the 'dialed number' window */
-       KO_MESSAGE,     /* the 'message' window */
-};
-
-enum drag_window {     /* which window are we dragging */
-       DRAG_NONE,
-       DRAG_LOCAL,     /* local video */
-       DRAG_REMOTE,    /* remote video */
-       DRAG_DIALED,    /* dialed number */
-       DRAG_INPUT,     /* input window */
-       DRAG_MESSAGE,   /* message window */
-};
 
-/*! \brief info related to the gui: button status, mouse coords, etc. */
 struct gui_info {
        enum kb_output          kb_output;      /* where the keyboard output goes */
-       enum drag_window        drag_window;    /* which window are we dragging */
-       int                     x_drag;         /* x coordinate where the drag starts */
-       int                     y_drag;         /* y coordinate where the drag starts */
+       struct drag_info        drag;           /* info on the window are we dragging */
        /* support for display. */
        SDL_Surface             *screen;        /* the main window */
 
@@ -107,16 +86,17 @@ struct gui_info {
        SDL_Surface             *font;          /* font to be used */ 
        SDL_Rect                font_rects[96]; /* only printable chars */
 
-       SDL_Rect                kp_msg;         /* incoming msg, relative to kpad */
-       SDL_Rect                kp_msg_s;       /* incoming msg, rel. to screen */
+       /* each board has two rectangles,
+        * [0] is the geometry relative to the keypad,
+        * [1] is the geometry relative to the whole screen
+        */
+       SDL_Rect                kp_msg[2];              /* incoming msg, relative to kpad */
        struct board            *bd_msg;
 
-       SDL_Rect                kp_edit;        /* edit user input */
-       SDL_Rect                kp_edit_s;      /* incoming msg, rel. to screen */
+       SDL_Rect                kp_edit[2];     /* edit user input */
        struct board            *bd_edit;
 
-       SDL_Rect                kp_dialed;      /* dialed number */
-       SDL_Rect                kp_dialed_s;    /* incoming msg, rel. to screen */
+       SDL_Rect                kp_dialed[2];   /* dialed number */
        struct board            *bd_dialed;
 
        /* variable-size array mapping keypad regions to functions */
@@ -234,8 +214,13 @@ enum skin_area {
        KEY_LOCALVIDEO = 133,
        KEY_REMOTEVIDEO = 134,
        KEY_FLASH = 136,
-       KEY_GUI_CLOSE = 199,            /* close gui */
 
+       /* sensitive areas for the various text windows */
+       KEY_MESSAGEBOARD = 140,
+       KEY_DIALEDBOARD = 141,
+       KEY_EDITBOARD = 142,
+
+       KEY_GUI_CLOSE = 199,            /* close gui */
        /* regions of the skin - displayed area, fonts, etc.
         * XXX NOTE these are not sensitive areas.
         */
@@ -319,10 +304,12 @@ static void keypad_pick_up(struct video_desc *env)
                ast_cli_command(gui->outfd, "console answer");
        } else { /* we have someone to call */
                char buf[160];
+               const char *who = ast_skip_blanks(read_message(gui->bd_msg));
                buf[sizeof(buf) - 1] = '\0';
-               snprintf(buf, sizeof(buf) - 1, "console dial %s",
-                       ast_skip_blanks(read_message(gui->bd_msg)));
+               snprintf(buf, sizeof(buf) - 1, "console dial %s", who);
                ast_log(LOG_WARNING, "doing <%s>\n", buf);
+               print_message(gui->bd_dialed, "\n");
+               print_message(gui->bd_dialed, who);
                reset_board(gui->bd_msg);
                ast_cli_command(gui->outfd, buf);
        }
@@ -357,6 +344,13 @@ static int video_geom(struct fbuf_t *b, const char *s);
 static void sdl_setup(struct video_desc *env);
 static int kp_match_area(const struct keypad_entry *e, int x, int y);
 
+static void set_drag(struct drag_info *drag, int x, int y, enum drag_window win)
+{
+       drag->x_start = x;
+       drag->y_start = y;
+       drag->drag_window = win;
+}
+
 /*
  * Handle SDL_MOUSEBUTTONDOWN type, finding the palette
  * index value and calling the right callback.
@@ -373,7 +367,7 @@ static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button
                button.x, button.y, gui->kp_used, gui->kp_size, gui->kp);
 #endif
        /* for each mousedown we end previous drag */
-       gui->drag_window = DRAG_NONE;
+       gui->drag.drag_window = DRAG_NONE;
 
        /* define keypad boundary */
        if (button.x < env->rem_dpy.w)
@@ -418,17 +412,17 @@ static void handle_mousedown(struct video_desc *env, SDL_MouseButtonEvent button
        case KEY_REMOTEVIDEO:
                break;
 
+       case KEY_MESSAGEBOARD:
+               if (button.button == SDL_BUTTON_LEFT)
+                       set_drag(&gui->drag, button.x, button.y, DRAG_MESSAGE);
+               break;
+
        /* press outside the keypad. right increases size, center decreases, left drags */
        case KEY_LOC_DPY:
        case KEY_REM_DPY:
                if (button.button == SDL_BUTTON_LEFT) {
-                       if (index == KEY_LOC_DPY) {
-                               /* store points where the drag start
-                               * and switch in drag mode */
-                               env->gui->x_drag = button.x;
-                               env->gui->y_drag = button.y;
-                               env->gui->drag_window = DRAG_LOCAL;
-                       }
+                       if (index == KEY_LOC_DPY)
+                               set_drag(&gui->drag, button.x, button.y, DRAG_LOCAL);
                        break;
                } else {
                        char buf[128];
@@ -523,34 +517,19 @@ static void handle_keyboard_input(struct video_desc *env, SDL_keysym *ks)
        return;
 }
 
-/* implement superlinear acceleration on the movement */
-static int move_accel(int delta)
-{
-       int d1 = delta*delta / 100;
-       return (delta > 0) ? delta + d1 : delta - d1;
-}
-
 static void grabber_move(struct video_out_desc *, int dx, int dy);
-/*
- * Move the source of the captured video.
- *
- * x_final_drag and y_final_drag are the coordinates where the drag ends,
- * start coordinares are in the gui_info structure.
- */
-static void move_capture_source(struct video_desc *env, int x_final_drag, int y_final_drag)
-{
-       int dx, dy;
 
-       /* move the origin */
-#define POLARITY -1            /* +1 or -1 depending on the desired direction */
-       dx = POLARITY*move_accel(x_final_drag - env->gui->x_drag) * 3;
-       dy = POLARITY*move_accel(y_final_drag - env->gui->y_drag) * 3;
+int compute_drag(int *start, int end, int magnifier);
+int compute_drag(int *start, int end, int magnifier)
+{
+       int delta = end - *start;
+#define POLARITY -1
+       /* add a small quadratic term */
+       delta += delta * delta * (delta > 0 ? 1 : -1 )/100;
+       delta *= POLARITY * magnifier;
 #undef POLARITY
-       env->gui->x_drag = x_final_drag;        /* update origin */
-       env->gui->y_drag = y_final_drag;
-
-       grabber_move(&env->out, dx, dy);
-       return;
+       *start = end;
+       return delta;
 }
 
 /*
@@ -565,12 +544,14 @@ static void move_capture_source(struct video_desc *env, int x_final_drag, int y_
 static void eventhandler(struct video_desc *env, const char *caption)
 {
        struct gui_info *gui = env->gui;
+       struct drag_info *drag;
 #define N_EVENTS       32
        int i, n;
        SDL_Event ev[N_EVENTS];
 
        if (!gui)
                return;
+       drag = &gui->drag;
        if (caption)
                SDL_WM_SetCaption(caption, NULL);
 
@@ -586,24 +567,24 @@ static void eventhandler(struct video_desc *env, const char *caption)
                                handle_keyboard_input(env, &ev[i].key.keysym);
                                break;
                        case SDL_MOUSEMOTION:
-                               if (gui->drag_window == DRAG_LOCAL)
-                                       move_capture_source(env, ev[i].motion.x, ev[i].motion.y);
-#if 0
-                               else if (gui->drag_window == DRAG_MESSAGE)
-                                       scroll_message(...);
-#endif
+                       case SDL_MOUSEBUTTONUP:
+                               if (drag->drag_window == DRAG_LOCAL) {
+                                       /* move the capture source */
+                                       int dx = compute_drag(&drag->x_start, ev[i].motion.x, 3);
+                                       int dy = compute_drag(&drag->y_start, ev[i].motion.y, 3);
+                                       grabber_move(&env->out, dx, dy);
+                               } else if (drag->drag_window == DRAG_MESSAGE) {
+                                       /* scroll up/down the window */
+                                       int dy = compute_drag(&drag->y_start, ev[i].motion.y, 1);
+                                       move_message_board(gui->bd_msg, dy);
+                               }
+                               if (ev[i].type == SDL_MOUSEBUTTONUP)
+                                       drag->drag_window = DRAG_NONE;
                                break;
                        case SDL_MOUSEBUTTONDOWN:
                                handle_mousedown(env, ev[i].button);
                                break;
-                       case SDL_MOUSEBUTTONUP:
-                               if (gui->drag_window == DRAG_LOCAL) {
-                                       move_capture_source(env, ev[i].button.x, ev[i].button.y);
-                                       gui->drag_window = DRAG_NONE;
-                               }
-                               break;
                        }
-
                }
        }
        if (1) {
@@ -646,7 +627,7 @@ static struct gui_info *gui_init(const char *keypad_file, const char *font)
                return NULL;
        /* initialize keypad status */
        gui->kb_output = KO_MESSAGE;    /* XXX temp */
-       gui->drag_window = DRAG_NONE;
+       gui->drag.drag_window = DRAG_NONE;
        gui->outfd = -1;
 
        keypad_setup(gui, keypad_file);
@@ -761,6 +742,21 @@ static void keypad_setup(struct gui_info *gui, const char *kp_file)
 struct board *board_setup(SDL_Surface *screen, SDL_Rect *dest,
        SDL_Surface *font, SDL_Rect *font_rects);
 
+/*! \brief initialize the boards we have in the keypad */
+static void init_board(struct gui_info *gui, struct board **dst, SDL_Rect *r, int dx, int dy)
+{
+       if (r[0].w == 0 || r[0].h == 0)
+               return; /* not available */
+       r[1] = r[0];    /* copy geometry */
+       r[1].x += dx;   /* add offset of main window */
+       r[1].y += dy;
+       if (*dst == NULL) {     /* initial call */
+               *dst = board_setup(gui->screen, &r[1], gui->font, gui->font_rects);
+       } else {
+               /* call a refresh */
+       }
+}
+
 /*! \brief [re]set the main sdl window, useful in case of resize.
  * We can tell the first from subsequent calls from the value of
  * env->gui, which is NULL the first time.
@@ -838,22 +834,14 @@ static void sdl_setup(struct video_desc *env)
        if (gui->keypad) {
                struct SDL_Rect *dest = &gui->win[WIN_KEYPAD].rect;
                struct SDL_Rect *src = (gui->kp_rect.w > 0 && gui->kp_rect.h > 0) ? & gui->kp_rect : NULL;
+               /* set the coordinates of the keypad relative to the main screen */
                dest->x = 2*BORDER + env->rem_dpy.w;
                dest->y = BORDER;
                dest->w = kp_w;
                dest->h = kp_h;
                SDL_BlitSurface(gui->keypad, src, gui->screen, dest);
-               if (gui->kp_msg.w > 0 && gui->kp_msg.h > 0) {
-                       gui->kp_msg_s = gui->kp_msg;
-                       gui->kp_msg_s.x += dest->x;
-                       gui->kp_msg_s.y += dest->y;
-                       if (!gui->bd_msg) {     /* initial call */
-                               gui->bd_msg = board_setup(gui->screen, &gui->kp_msg_s,
-                                       gui->font, gui->font_rects);
-                       } else {
-                               /* call a refresh */
-                       }
-               }
+               init_board(gui, &gui->bd_msg, gui->kp_msg, dest->x, dest->y);
+               init_board(gui, &gui->bd_dialed, gui->kp_dialed, dest->x, dest->y);
                SDL_UpdateRects(gui->screen, 1, dest);
        }
        return;
@@ -911,6 +899,9 @@ static struct _s_k gui_key_map[] = {
         {"LOCALVIDEO", KEY_LOCALVIDEO },
         {"REMOTEVIDEO",        KEY_REMOTEVIDEO },
         {"GUI_CLOSE",  KEY_GUI_CLOSE },
+        {"MESSAGEBOARD",       KEY_MESSAGEBOARD },
+        {"DIALEDBOARD",        KEY_DIALEDBOARD },
+        {"EDITBOARD",  KEY_EDITBOARD },
         {"KEYPAD",     KEY_KEYPAD },   /* x0 y0 w h - active area of the keypad */
         {"MESSAGE",    KEY_MESSAGE },  /* x0 y0 w h - incoming messages */
         {"DIALED",     KEY_DIALED },   /* x0 y0 w h - dialed number */
@@ -972,11 +963,11 @@ static int keypad_cfg_read(struct gui_info *gui, const char *val)
                if (e.c == KEY_KEYPAD)  /* active keypad area */
                        r = &gui->kp_rect;
                else if (e.c == KEY_MESSAGE)
-                       r = &gui->kp_msg;
+                       r = gui->kp_msg;
                else if (e.c == KEY_DIALED)
-                       r = &gui->kp_dialed;
+                       r = gui->kp_dialed;
                else if (e.c == KEY_EDIT)
-                       r = &gui->kp_edit;
+                       r = gui->kp_edit;
                if (r) {
                        r->x = atoi(s2);
                        r->y = e.x0;
index 8314da3..f426a54 100644 (file)
@@ -87,8 +87,34 @@ void console_video_uninit(struct video_desc *env);
 void console_video_start(struct video_desc *env, struct ast_channel *owner);
 
 /* console_board.c */
+
+/* Where do we send the keyboard/keypad output */
+enum kb_output {
+       KO_NONE,
+       KO_INPUT,       /* the local input window */
+       KO_DIALED,      /* the 'dialed number' window */
+       KO_MESSAGE,     /* the 'message' window */
+};
+
+enum drag_window {     /* which window are we dragging */
+       DRAG_NONE,
+       DRAG_LOCAL,     /* local video */
+       DRAG_REMOTE,    /* remote video */
+       DRAG_DIALED,    /* dialed number */
+       DRAG_INPUT,     /* input window */
+       DRAG_MESSAGE,   /* message window */
+};
+
+/*! \brief support for drag actions */
+struct drag_info {
+       int             x_start;        /* last known mouse position */
+       int             y_start;
+       enum drag_window drag_window;
+};
+/*! \brief info related to the gui: button status, mouse coords, etc. */
 struct board;
 /* !\brief print a message on a board */
+void move_message_board(struct board *b, int dy);
 int print_message(struct board *b, const char *s);
 
 /*! \brief return the whole text from a board */