added support for special media buttons on Amazon Fire TV remote control
[rocksndiamonds.git] / src / libgame / gadgets.c
index b21ecdca09607e9afb25eb4dec7f1fb8ad302e19..6b7d2592f435849b3bd8fb0f8798227278a18ca7 100644 (file)
@@ -24,8 +24,6 @@
 #define DG_BUFFERED            0
 #define DG_DIRECT              1
 
-#define GADGET_DEACTIVATED(g)  ((g)->x < 0 || (g)->y < 0)
-
 #define OPTION_TEXT_SELECTABLE(g, t)                                   \
   (t[0] != g->selectbox.char_unselectable &&                           \
    t[0] != '\0' &&                                                     \
@@ -220,7 +218,7 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
   int state = (pressed ? GD_BUTTON_PRESSED : GD_BUTTON_UNPRESSED);
   boolean redraw_selectbox = FALSE;
 
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   gd = (!gi->active ? &gi->alt_design[state] :
@@ -244,9 +242,16 @@ static void DrawGadget(struct GadgetInfo *gi, boolean pressed, boolean direct)
        int deco_width  = MIN(gi->deco.width,  gi->width  - deco_x);
        int deco_height = MIN(gi->deco.height, gi->height - deco_y);
 
-       BlitBitmap(gi->deco.design.bitmap, drawto,
-                  gi->deco.design.x, gi->deco.design.y,
-                  deco_width, deco_height, gi->x + deco_x, gi->y + deco_y);
+       if (gi->deco.masked)
+         BlitBitmapMasked(gi->deco.design.bitmap, drawto,
+                          gi->deco.design.x, gi->deco.design.y,
+                          deco_width, deco_height,
+                          gi->x + deco_x, gi->y + deco_y);
+       else
+         BlitBitmap(gi->deco.design.bitmap, drawto,
+                    gi->deco.design.x, gi->deco.design.y,
+                    deco_width, deco_height,
+                    gi->x + deco_x, gi->y + deco_y);
       }
 
       break;
@@ -770,7 +775,7 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
 {
   int tag = first_tag;
 
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   while (tag != GDI_END)
@@ -994,6 +999,10 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
        gi->deco.yshift = va_arg(ap, int);
        break;
 
+      case GDI_DECORATION_MASKED:
+       gi->deco.masked = (boolean)va_arg(ap, int);
+       break;
+
       case GDI_EVENT_MASK:
        gi->event_mask = va_arg(ap, unsigned int);
        break;
@@ -1086,11 +1095,17 @@ static void HandleGadgetTags(struct GadgetInfo *gi, int first_tag, va_list ap)
     tag = va_arg(ap, int);     /* read next tag */
   }
 
-  /* check if gadget is complete */
+  gi->deactivated = FALSE;
+
+  /* check if gadget has undefined bitmaps */
   if (gi->type != GD_TYPE_DRAWING_AREA &&
-      (!gi->design[GD_BUTTON_UNPRESSED].bitmap ||
-       !gi->design[GD_BUTTON_PRESSED].bitmap))
-    Error(ERR_EXIT, "gadget incomplete (missing Bitmap)");
+      (gi->design[GD_BUTTON_UNPRESSED].bitmap == NULL ||
+       gi->design[GD_BUTTON_PRESSED].bitmap == NULL))
+    gi->deactivated = TRUE;
+
+  /* check if gadget is placed off-screen */
+  if (gi->x < 0 || gi->y < 0)
+    gi->deactivated = TRUE;
 
   /* adjust gadget values in relation to other gadget values */
 
@@ -1252,7 +1267,7 @@ void ModifyGadget(struct GadgetInfo *gi, int first_tag, ...)
 
 void RedrawGadget(struct GadgetInfo *gi)
 {
-  if (gi == NULL)
+  if (gi == NULL || gi->deactivated)
     return;
 
   if (gi->mapped)
@@ -1340,7 +1355,7 @@ static struct GadgetInfo *last_gi = NULL;
 
 static void MapGadgetExt(struct GadgetInfo *gi, boolean redraw)
 {
-  if (gi == NULL || gi->mapped || GADGET_DEACTIVATED(gi))
+  if (gi == NULL || gi->deactivated || gi->mapped)
     return;
 
   gi->mapped = TRUE;
@@ -1356,7 +1371,7 @@ void MapGadget(struct GadgetInfo *gi)
 
 void UnmapGadget(struct GadgetInfo *gi)
 {
-  if (gi == NULL || !gi->mapped)
+  if (gi == NULL || gi->deactivated || !gi->mapped)
     return;
 
   gi->mapped = FALSE;
@@ -1590,6 +1605,8 @@ boolean HandleGadgets(int mx, int my, int button)
 
     if (gadget_pressed_inside_select_line)
       new_gi = NULL;
+
+    StopTextInput();
   }
 
   gadget_pressed =
@@ -1691,6 +1708,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
       if (gi->textinput.cursor_position != old_cursor_position)
        DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+
+      if (press_event)
+       StartTextInput(gi->x, gi->y, gi->width, gi->height);
     }
     else if (gi->type & GD_TYPE_TEXT_AREA && button != 0 && !motion_status)
     {
@@ -1705,6 +1725,9 @@ boolean HandleGadgets(int mx, int my, int button)
 
       if (gi->textarea.cursor_position != old_cursor_position)
        DrawGadget(gi, DG_PRESSED, gi->direct_draw);
+
+      if (press_event)
+       StartTextInput(gi->x, gi->y, gi->width, gi->height);
     }
     else if (gi->type & GD_TYPE_SELECTBOX && gi->selectbox.open &&
             !keep_selectbox_open)
@@ -1735,7 +1758,7 @@ boolean HandleGadgets(int mx, int my, int button)
       new_gi->event.type = GD_EVENT_INFO_ENTERING;
       new_gi->callback_info(new_gi);
     }
-    else if (last_info_gi != NULL)
+    else if (last_info_gi != NULL && last_info_gi->mapped)
     {
       last_info_gi->event.type = GD_EVENT_INFO_LEAVING;
       last_info_gi->callback_info(last_info_gi);
@@ -2061,13 +2084,17 @@ boolean HandleGadgetsKeyInput(Key key)
 {
   struct GadgetInfo *gi = last_gi;
 
-  if (gi == NULL || !gi->mapped ||
+  if (gi == NULL || gi->deactivated || !gi->mapped ||
       !(gi->type & GD_TYPE_TEXT_INPUT ||
        gi->type & GD_TYPE_TEXT_AREA ||
        gi->type & GD_TYPE_SELECTBOX))
     return FALSE;
 
-  if (key == KSYM_Return)      /* valid for both text input and selectbox */
+  if (key == KSYM_Escape)
+  {
+    StopTextInput();
+  }
+  else if (key == KSYM_Return) /* valid for both text input and selectbox */
   {
     boolean gadget_changed = ((gi->event_mask & GD_EVENT_TEXT_RETURN) != 0);
 
@@ -2079,6 +2106,8 @@ boolean HandleGadgetsKeyInput(Key key)
        strcpy(gi->textinput.last_value, gi->textinput.value);
       else
        gadget_changed = FALSE;
+
+      StopTextInput();
     }
     else if (gi->type & GD_TYPE_SELECTBOX)
     {