예제 #1
0
/****************************************************************************
 *
 * Initiates a menu pop-up
 *
 * Style = 1 = sticky menu, stays up on initial button release.
 * Style = 0 = transient menu, drops on initial release.
 ***************************************************************************/
int do_menu(MenuRoot * menu, int style)
{
  int prevStashedX = 0, prevStashedY = 0;
  MenuRoot *PrevActiveMenu = 0;
  MenuItem *PrevActiveItem = 0;
  int retval = MENU_NOP;
  int x, y;
  Time t0;
  extern Time lastTimestamp;
  int PrevMenuX = PrevActiveMenuX;

  /* this condition could get ugly */
  if (menu->in_use)
    return MENU_ERROR;

  /* In case we wind up with a move from a menu which is
   * from a window border, we'll return to here to start
   * the move */
  XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,
		&x, &y, &JunkX, &JunkY, &JunkMask);

  if (menu_on) {
    prevStashedX = Stashed_X;
    prevStashedY = Stashed_Y;

    PrevActiveMenu = ActiveMenu;
    PrevActiveItem = ActiveItem;

    if (ActiveMenu)
      x = Stashed_X + ActiveMenu->width - 3;

    if (ActiveItem)
      y = ActiveItem->y_offset + MenuY;
  } else {
    mouse_moved = 0;
    t0 = lastTimestamp;
    if (!GrabEm(MENU)) {
      XBell(dpy, Scr.screen);
      return MENU_DONE;
    }
    x += 2;
  }
  if (PopUpMenu(menu, x, y)) {
    retval = UpdateMenu(style);
  } else
    XBell(dpy, Scr.screen);

  ActiveMenu = PrevActiveMenu;
  ActiveItem = PrevActiveItem;
  if ((ActiveItem) && (menu_on))
    ActiveItem->state = 1;
  Stashed_X = prevStashedX;
  Stashed_Y = prevStashedY;


  if (!menu_on) {
    UngrabEm();
    WaitForButtonsUp();
  }
  if (((lastTimestamp - t0) < 3 * Scr.ClickTime) && (mouse_moved == 0))
    menu_aborted = 1;
  else
    menu_aborted = 0;

  PrevActiveMenuX = PrevMenuX;
  return retval;
}
예제 #2
0
/*****************************************************************************
 *
 * Builtin which determines if the button press was a click or double click...
 *
 ****************************************************************************/
void ComplexFunction(XEvent * eventp, Window w, FvwmWindow * tmp_win,
                     unsigned long context, char *action, int *Module)
{
    char type = MOTION;
    char c;
    MenuItem *mi;
    Bool Persist = False;
    Bool HaveDoubleClick = False;
    Bool NeedsTarget = False;
    char *arguments[10], *junk, *taction;
    int x, y, i;
    XEvent d, *ev;
    MenuRoot *mr;
    extern Bool desperate;

    mr = FindPopup(action);
    if (mr == NULL) {
        if (!desperate)
            fvwm_msg(ERR, "ComplexFunction", "No such function %s", action);
        return;
    }
    desperate = 0;
    /* Get the argument list */
    /* First entry in action is the function-name, ignore it */
    action = GetNextToken(action, &junk);
    if (junk != NULL)
        free(junk);
    for (i = 0; i < 10; i++)
        action = GetNextToken(action, &arguments[i]);
    /* These built-ins require a selected window
     * The function code is >= 100 and < 1000
     * F_RESIZE
     * F_MOVE
     * F_ICONIFY
     * F_RAISE
     * F_LOWER
     * F_DESTROY
     * F_DELETE
     * F_STICK
     * F_RAISELOWER
     * F_MAXIMIZE
     * F_FOCUS
     *
     * These do not:
     * The function code is < 100
     * F_NOP
     * F_TITLE
     * F_BEEP
     * F_SCROLL
     * F_MOVECURSOR
     * F_RESTART
     * F_EXEC
     * F_REFRESH
     * F_GOTO_PAGE
     * F_TOGGLE_PAGE
     * F_CIRCULATE_UP
     * F_CIRCULATE_DOWN
     * F_WARP
     * F_DESK
     * F_MODULE
     * F_POPUP
     * F_QUIT
     * F_WINDOWLIST
     * F_FUNCTION
     * F_SEND_WINDOW_LIST
     */
    ev = eventp;
    /* In case we want to perform an action on a button press, we
     * need to fool other routines */
    if (eventp->type == ButtonPress)
        eventp->type = ButtonRelease;
    mi = mr->first;
    while (mi != NULL) {
        /* make lower case */
        c = *(mi->item);
        if ((mi->func_type >= 100) && (mi->func_type < 1000))
            NeedsTarget = True;
        if (isupper(c))
            c = tolower(c);
        if (c == DOUBLE_CLICK) {
            HaveDoubleClick = True;
            Persist = True;
        } else if (c == IMMEDIATE) {
            if (tmp_win)
                w = tmp_win->frame;
            else
                w = None;
            taction = expand(mi->action, arguments, tmp_win);
            ExecuteFunction(taction, tmp_win, eventp, context, -2);
            free(taction);
        } else
            Persist = True;
        mi = mi->next;
    }

    if (!Persist) {
        for (i = 0; i < 10; i++)
            if (arguments[i] != NULL)
                free(arguments[i]);
        return;
    }

    /* Only defer execution if there is a possibility of needing
     * a window to operate on */
    if (NeedsTarget) {
        if (DeferExecution
                (eventp, &w, &tmp_win, &context, SELECT, ButtonPress)) {
            WaitForButtonsUp();
            for (i = 0; i < 10; i++)
                if (arguments[i] != NULL)
                    free(arguments[i]);
            return;
        }
    }

    if (!GrabEm(SELECT)) {
        XBell(dpy, Scr.screen);
        for (i = 0; i < 10; i++)
            if (arguments[i] != NULL)
                free(arguments[i]);
        return;
    }
    XQueryPointer(dpy, Scr.Root, &JunkRoot, &JunkChild,
                  &x, &y, &JunkX, &JunkY, &JunkMask);


    /* Wait and see if we have a click, or a move */
    /* wait 100 msec, see if the user releases the button */
    if (IsClick(x, y, ButtonReleaseMask, &d)) {
        ev = &d;
        type = CLICK;
    }

    /* If it was a click, wait to see if its a double click */
    if ((HaveDoubleClick) && (type == CLICK) &&
            (IsClick(x, y, ButtonPressMask, &d))) {
        type = ONE_AND_A_HALF_CLICKS;
        ev = &d;
    }
    if ((HaveDoubleClick) && (type == ONE_AND_A_HALF_CLICKS) &&
            (IsClick(x, y, ButtonReleaseMask, &d))) {
        type = DOUBLE_CLICK;
        ev = &d;
    }
    /* some functions operate on button release instead of
     * presses. These gets really weird for complex functions ... */
    if (ev->type == ButtonPress)
        ev->type = ButtonRelease;

    mi = mr->first;
    while (mi != NULL) {
        /* make lower case */
        c = *(mi->item);
        if (isupper(c))
            c = tolower(c);
        if (c == type) {
            if (tmp_win)
                w = tmp_win->frame;
            else
                w = None;
            taction = expand(mi->action, arguments, tmp_win);
            ExecuteFunction(taction, tmp_win, ev, context, -2);
            free(taction);
        }
        mi = mi->next;
    }
    WaitForButtonsUp();
    UngrabEm();
    for (i = 0; i < 10; i++)
        if (arguments[i] != NULL)
            free(arguments[i]);
}
예제 #3
0
/***********************************************************************
 *
 *  Procedure:
 *	ExecuteFunction - execute a fvwm built in function
 *
 *  Inputs:
 *	Action	- the menu action to execute
 *	tmp_win	- the fvwm window structure
 *	eventp	- pointer to the event that caused the function
 *	context - the context in which the button was pressed
 *
 ***********************************************************************/
void ExecuteFunction(char *Action, FvwmWindow *tmp_win, XEvent *eventp,
		     unsigned long context, int Module)
{
  Window w;
  int matched,j;
  char *function;
  char *action, *taction;
  char *arguments[10];
  struct functions *bif;

  if (!Action || Action[0] == 0 || Action[1] == 0)
  {
    /* impossibly short command */
    return;                             /* done */
  }
  if (Action[0] == '#') {               /* a comment */
    return;                             /* done */
  }
  /* Note: the module config command, "*" can not be handled by the
     regular command table because there is no required white space after
     the asterisk. */
  if (Action[0] == '*') {               /* a module config command */
    ModuleConfig(NULL,0,0,0,Action,0);  /* process the command */
    return;                             /* done */
  }

  for(j=0;j<10;j++)
    arguments[j] = NULL;

  if(tmp_win == NULL)
    w = Scr.Root;
  else
    w = tmp_win->w;

  if((tmp_win) &&(eventp))
    w = eventp->xany.window;
  if((tmp_win)&&(eventp->xbutton.subwindow != None)&&
     (eventp->xany.window != tmp_win->w))
    w = eventp->xbutton.subwindow;

  taction = expand(Action,arguments,tmp_win);
  action = GetNextToken(taction,&function);
  if (!function)
    return;
  j=0;
  matched = FALSE;

  bif = FindBuiltinFunction(function);
  if (bif)
  {
    matched = TRUE;
    bif->action(eventp,w,tmp_win,context,action,&Module);
  }

  if(!matched)
    {
      desperate = 1;
      ComplexFunction(eventp,w,tmp_win,context,taction, &Module);
      if(desperate)
	executeModule(eventp,w,tmp_win,context,taction, &Module);
      desperate = 0;
    }

  /* Only wait for an all-buttons-up condition after calls from
   * regular built-ins, not from complex-functions or modules. */
  if(Module == -1)
    WaitForButtonsUp();

  if (function)
    free(function);
  if(taction != NULL)
    free(taction);
  return;
}