示例#1
0
void EvtMouseVScrollBar(struct XObj *xobj, XButtonEvent *EvtButton)
{
	static XEvent event;
	int oldy = 0;
	int oldvalue = -1;
	int newvalue;
	int x1,y1,x2,y2;
	Window Win1,Win2;
	unsigned int modif;
	fd_set in_fdset;

	do
	{
		/* On suit les mouvements de la souris */
		FQueryPointer(dpy, *xobj->ParentWin, &Win1, &Win2,
			      &x1, &y1, &x2, &y2, &modif);
		y2 = y2 - xobj->y;
		if (y2 < 15)
			y2 = 15;
		if (y2 > xobj->height - 21)
			y2 = xobj->height - 21;
		if (oldy != y2)
		{
			oldy = y2;
			/* calcule de xobj->value */
			newvalue = (y2-15)*xobj->height/(xobj->height - 36) *
				(xobj->value2 - xobj->value3) /
				(xobj->height) + xobj->value3;
			if (newvalue!=oldvalue)
			{
				HideThumbV(xobj);
				xobj->value = newvalue;
				DrawThumbV(xobj, NULL);
				oldvalue = newvalue;
				SendMsg(xobj,SingleClic);
				XSync(dpy,0);
				usleep(10000);
			}
		}
		FD_ZERO(&in_fdset);
		FD_SET(x_fd, &in_fdset);
		select(32, SELECT_FD_SET_CAST &in_fdset, NULL, NULL, NULL);
	}
	while (!FCheckTypedEvent(dpy, ButtonRelease, &event) &&
	       EvtButton != NULL);
}
示例#2
0
文件: focus.c 项目: fvwmorg/fvwm
/* same as above, but forces to regrab buttons on the window under the pointer
 * if necessary */
void focus_grab_buttons_on_pointer_window(void)
{
	Window w;
	FvwmWindow *fw;

	if (!FQueryPointer(
		    dpy, Scr.Root, &JunkRoot, &w, &JunkX, &JunkY, &JunkX,
		    &JunkY, &JunkMask))
	{
		/* pointer is not on this screen */
		return;
	}
	if (XFindContext(dpy, w, FvwmContext, (caddr_t *) &fw) == XCNOENT)
	{
		/* pointer is not over a window */
		return;
	}
	focus_grab_buttons(fw);

	return;
}
示例#3
0
void EvtMousePopupMenu(struct XObj *xobj, XButtonEvent *EvtButton)
{
  static XEvent event;
  int x,y,hOpt,yMenu,hMenu;
  int x1,y1,x2,y2,oldy;
  int oldvalue = 0;
  int newvalue = 0;
  Window Win1,Win2,WinPop;
  unsigned int modif;
  unsigned long mask;
  unsigned long while_mask;
  XSetWindowAttributes Attr;
  Time start_time = 0;
  KeySym ks;
  unsigned char buf[10];
  Bool End = 1;
  int asc = xobj->Ffont->ascent;

  hOpt = xobj->Ffont->height + 10;
  xobj->value3 = CountOption(xobj->title);
  yMenu = xobj->y - ((xobj->value-1) * hOpt);
  hMenu = xobj->value3 * hOpt;

  /* Creation de la fenetre menu */
  XTranslateCoordinates(dpy, *xobj->ParentWin, Root,
			xobj->x, yMenu, &x, &y, &Win1);
  if (x < 0) x = 0;
  if (y < 0) y = 0;
  if (x+xobj->width > XDisplayWidth(dpy, screen))
    x = XDisplayWidth(dpy, screen) - xobj->width;
  if (y+hMenu > XDisplayHeight(dpy, screen))
    y = XDisplayHeight(dpy, screen) - hMenu;
  mask = 0;
  Attr.background_pixel = xobj->TabColor[back];
  mask |= CWBackPixel;
  Attr.border_pixel = 0;
  mask |= CWBorderPixel;
  Attr.colormap = Pcmap;
  mask |= CWColormap;
  Attr.cursor = XCreateFontCursor(dpy, XC_hand2);
  mask |= CWCursor;             /* Curseur pour la fenetre / Window cursor */
  Attr.override_redirect = True;
  mask |= CWOverrideRedirect;
  WinPop = XCreateWindow(dpy, Root, x, y, xobj->width, hMenu, 0,
			 Pdepth, InputOutput, Pvisual, mask, &Attr);
  if (xobj->colorset >= 0)
    SetWindowBackground(dpy, WinPop, xobj->width, hMenu,
			&Colorset[xobj->colorset], Pdepth,
			xobj->gc, True);
  XMapRaised(dpy, WinPop);

  /* Dessin du menu / Drawing the menu */
  DrawPMenu(xobj, WinPop, hOpt, 0);
  XGrabPointer(dpy, WinPop, True, GRAB_EVMASK, GrabModeAsync, GrabModeAsync,
	       None, None, CurrentTime);
  if (EvtButton == NULL) {
    while_mask = ButtonPress;
  }
  else {
    start_time = EvtButton->time;
    while_mask = ButtonRelease;
  }

  while (End)
  {
    FQueryPointer(dpy, Root, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif);
    /* Determiner l'option courante / Current option */
    y2 = y2 - y;
    x2 = x2 - x;
    oldy = y2;
    /* calcule de xobj->value / compute xobj->value */
    if ((x2 > 0) && (x2 < xobj->width) && (y2 > 0) && (y2 < hMenu))
      newvalue = y2 / hOpt+1;
    else
      newvalue = 0;
    if (newvalue != oldvalue)
    {
      UnselectMenu(xobj, WinPop, hOpt, oldvalue, xobj->width, asc, 0);
      SelectMenu(xobj, WinPop, hOpt, newvalue);
      oldvalue = newvalue;
    }

    FNextEvent(dpy, &event);
    switch (event.type)
    {
    case KeyPress:
      XLookupString(&event.xkey, (char *)buf, sizeof(buf), &ks, NULL);
      if (ks == XK_Escape) {
	newvalue = 0;
	End = 0;
      }
      else if (ks == XK_Return) {
	End = 0;
      }
      else if (ks == XK_Up && y2 >= hOpt) {
	FWarpPointer(dpy, None, None, 0, 0, 0, 0, 0, -hOpt);
      }
      else if (ks == XK_Down && y2 + hOpt <= hMenu) {
	FWarpPointer(dpy, None, None, 0, 0, 0, 0, 0, hOpt);
      }
      break;
    case ButtonPress:
      if (while_mask == ButtonPress)
	End = 0;
      break;
    case ButtonRelease:
      if (start_time != 0 && event.xbutton.time - start_time < MENU_DRAG_TIME) {
	while_mask = ButtonPress;
	start_time = 0;
      }
      if (while_mask == ButtonRelease)
	End = 0;
      break;
    }
  }
#if 0
  do
  {
    FQueryPointer(dpy, Root, &Win1, &Win2, &x1, &y1, &x2, &y2, &modif);
    /* Determiner l'option courante / Current option */
    y2 = y2 - y;
    x2 = x2 - x;
    {
      oldy = y2;
      /* calcule de xobj->value / compute xobj->value */
      if ((x2 > 0) && (x2 < xobj->width) && (y2 > 0) && (y2 < hMenu))
	newvalue = y2 / hOpt+1;
      else
	newvalue = 0;
      if (newvalue != oldvalue)
      {
	UnselectMenu(xobj, WinPop, hOpt, oldvalue, xobj->width, asc, 0);
	SelectMenu(xobj, WinPop, hOpt, newvalue);
	oldvalue = newvalue;
      }
    }
    FD_ZERO(&in_fdset);
    FD_SET(x_fd, &in_fdset);
    select(32, SELECT_FD_SET_CAST &in_fdset, NULL, NULL, NULL);
  }
  while (!FCheckTypedEvent(dpy, while_mask, &event));
#endif
 XUngrabPointer(dpy, CurrentTime);
 XSync(dpy,0);

 XDestroyWindow(dpy, WinPop);
 if (newvalue != 0)
 {
   xobj->value = newvalue;
   SendMsg(xobj, SingleClic);
 }
}
示例#4
0
static void execute_complex_function(
	cond_rc_t *cond_rc, const exec_context_t *exc, char *action,
	Bool *desperate, Bool has_ref_window_moved)
{
	cond_rc_t tmp_rc;
	cfunc_action_t type = CF_MOTION;
	char c;
	FunctionItem *fi;
	Bool Persist = False;
	Bool HaveDoubleClick = False;
	Bool HaveHold = False;
	Bool NeedsTarget = False;
	Bool ImmediateNeedsTarget = False;
	int do_allow_unmanaged = FUNC_ALLOW_UNMANAGED;
	int do_allow_unmanaged_immediate = FUNC_ALLOW_UNMANAGED;
	char *arguments[11], *taction;
	char *func_name;
	int x, y ,i;
	XEvent d;
	FvwmFunction *func;
	static int depth = 0;
	const exec_context_t *exc2;
	exec_context_changes_t ecc;
	exec_context_change_mask_t mask;
	int trigger_evtype;
	int button;
	XEvent *te;

	if (cond_rc == NULL)
	{
		condrc_init(&tmp_rc);
		cond_rc = &tmp_rc;
	}
	cond_rc->rc = COND_RC_OK;
	mask = 0;
	d.type = 0;
	ecc.w.fw = exc->w.fw;
	ecc.w.w = exc->w.w;
	ecc.w.wcontext = exc->w.wcontext;
	/* find_complex_function expects a token, not just a quoted string */
	func_name = PeekToken(action, &taction);
	if (!func_name)
	{
		return;
	}
	func = find_complex_function(func_name);
	if (func == NULL)
	{
		if (*desperate == 0)
		{
			fvwm_msg(
				ERR, "ComplexFunction", "No such function %s",
				action);
		}
		return;
	}
	if (!depth)
	{
		Scr.flags.is_executing_complex_function = 1;
	}
	depth++;
	*desperate = 0;
	/* duplicate the whole argument list for use as '$*' */
	if (taction)
	{
		arguments[0] = safestrdup(taction);
		/* strip trailing newline */
		if (arguments[0][0])
		{
			int l= strlen(arguments[0]);

			if (arguments[0][l - 1] == '\n')
			{
				arguments[0][l - 1] = 0;
			}
		}
		/* Get the argument list */
		for (i = 1; i < 11; i++)
		{
			taction = GetNextToken(taction, &arguments[i]);
		}
	}
	else
	{
		for (i = 0; i < 11; i++)
		{
			arguments[i] = NULL;
		}
	}
	/* In case we want to perform an action on a button press, we
	 * need to fool other routines */
	te = exc->x.elast;
	if (te->type == ButtonPress)
	{
		trigger_evtype = ButtonRelease;
	}
	else
	{
		trigger_evtype = te->type;
	}
	func->use_depth++;

	for (fi = func->first_item; fi != NULL; fi = fi->next_item)
	{
		if (fi->flags & FUNC_NEEDS_WINDOW)
		{
			NeedsTarget = True;
			do_allow_unmanaged &= fi->flags;
			if (fi->condition == CF_IMMEDIATE)
			{
				do_allow_unmanaged_immediate &= fi->flags;
				ImmediateNeedsTarget = True;
				break;
			}
		}
	}

	if (ImmediateNeedsTarget)
	{
		if (DeferExecution(
			    &ecc, &mask, CRS_SELECT, trigger_evtype,
			    do_allow_unmanaged_immediate))
		{
			func->use_depth--;
			__cf_cleanup(&depth, arguments, cond_rc);
			return;
		}
		NeedsTarget = False;
	}
	else
	{
		ecc.w.w = (ecc.w.fw) ? FW_W_FRAME(ecc.w.fw) : None;
		mask |= ECC_W;
	}

	/* we have to grab buttons before executing immediate actions because
	 * these actions can move the window away from the pointer so that a
	 * button release would go to the application below. */
	if (!GrabEm(CRS_NONE, GRAB_NORMAL))
	{
		func->use_depth--;
		fvwm_msg(
			ERR,
			"ComplexFunction", "Grab failed in function %s,"
			" unable to execute immediate action", action);
		__cf_cleanup(&depth, arguments, cond_rc);
		return;
	}
	exc2 = exc_clone_context(exc, &ecc, mask);
	__run_complex_function_items(
		cond_rc, CF_IMMEDIATE, func, exc2, arguments,
		has_ref_window_moved);
	exc_destroy_context(exc2);
	for (fi = func->first_item;
	     fi != NULL && cond_rc->break_levels == 0;
	     fi = fi->next_item)
	{
		/* c is already lowercase here */
		c = fi->condition;
		switch (c)
		{
		case CF_IMMEDIATE:
			break;
		case CF_DOUBLE_CLICK:
			HaveDoubleClick = True;
			Persist = True;
			break;
		case CF_HOLD:
			HaveHold = True;
			Persist = True;
			break;
		default:
			Persist = True;
			break;
		}
	}

	if (!Persist || cond_rc->break_levels != 0)
	{
		func->use_depth--;
		__cf_cleanup(&depth, arguments, cond_rc);
		UngrabEm(GRAB_NORMAL);
		return;
	}

	/* Only defer execution if there is a possibility of needing
	 * a window to operate on */
	if (NeedsTarget)
	{
		if (DeferExecution(
			    &ecc, &mask, CRS_SELECT, trigger_evtype,
			    do_allow_unmanaged))
		{
			func->use_depth--;
			__cf_cleanup(&depth, arguments, cond_rc);
			UngrabEm(GRAB_NORMAL);
			return;
		}
	}

	te = (mask & ECC_ETRIGGER) ? ecc.x.etrigger : exc->x.elast;
	switch (te->xany.type)
	{
	case ButtonPress:
	case ButtonRelease:
		x = te->xbutton.x_root;
		y = te->xbutton.y_root;
		button = te->xbutton.button;
		/* Take the click which started this fuction off the
		 * Event queue.  -DDN- Dan D Niles [email protected] */
		FCheckMaskEvent(dpy, ButtonPressMask, &d);
		break;
	default:
		if (FQueryPointer(
			    dpy, Scr.Root, &JunkRoot, &JunkChild, &x, &y,
			    &JunkX, &JunkY, &JunkMask) == False)
		{
			/* pointer is on a different screen */
			x = 0;
			y = 0;
		}
		button = 0;
		break;
	}

	/* Wait and see if we have a click, or a move */
	/* wait forever, see if the user releases the button */
	type = CheckActionType(x, y, &d, HaveHold, True, &button);
	if (type == CF_CLICK)
	{
		int button2;

		/* If it was a click, wait to see if its a double click */
		if (HaveDoubleClick)
		{
			type = CheckActionType(
				x, y, &d, True, False, &button2);
			switch (type)
			{
			case CF_HOLD:
			case CF_MOTION:
			case CF_CLICK:
				if (button == button2)
				{
					type = CF_DOUBLE_CLICK;
				}
				else
				{
					type = CF_CLICK;
				}
				break;
			case CF_TIMEOUT:
				type = CF_CLICK;
				break;
			default:
				/* can't happen */
				break;
			}
		}
	}
	else if (type == CF_TIMEOUT)
	{
		type = CF_HOLD;
	}

	/* some functions operate on button release instead of presses. These
	 * gets really weird for complex functions ... */
	if (d.type == ButtonPress)
	{
		d.type = ButtonRelease;
		if (d.xbutton.button > 0 &&
		    d.xbutton.button <= NUMBER_OF_MOUSE_BUTTONS)
		{
			d.xbutton.state &=
				(~(Button1Mask >> (d.xbutton.button - 1)));
		}
示例#5
0
void menu_shortcuts(
	struct MenuRoot *mr, struct MenuParameters *pmp,
	struct MenuReturn *pmret, XEvent *event, struct MenuItem **pmi_current,
	double_keypress *pdkp, int *ret_menu_x, int *ret_menu_y)
{
	int with_control;
	int with_shift;
	int with_meta;
	KeySym keysym;
	char ckeychar;
	int ikeychar;
	MenuItem *new_item;
	MenuItem *mi_current;
	int index;
	int mx;
	int my;
	int menu_x;
	int menu_y;
	int menu_width;
	int menu_height;
	int items_to_move;
	int do_skip_section;
	menu_shortcut_action saction;
	Binding *binding;
	int context;
	int is_geometry_known;
	char *command;

	ckeychar = 0;
	new_item = NULL;
	mi_current = pmi_current ? *pmi_current : NULL;
	do_skip_section = 0;
	saction = SA_NONE;
	context = C_MENU;
	is_geometry_known = 0;
	context = C_MENU;
	command = 0;
	if (mi_current)
	{
		if (MI_IS_TITLE(mi_current))
		{
			context |= C_TITLE;
		}
		else
		{
			/* menu item context, use I (icon) for it */
			context |= C_MENU_ITEM;
		}
	}
	else
	{
		if (
			menu_get_geometry(
				mr, &JunkRoot, &menu_x, &menu_y, &menu_width,
				&menu_height, &JunkBW, &JunkDepth))
		{
			is_geometry_known = 1;
			if (
				FQueryPointer(
					dpy, Scr.Root, &JunkRoot, &JunkChild,
					&mx, &my, &JunkX, &JunkY, &JunkMask) ==
				0)
			{
				/* pointer is on a different screen */
				mx = 0;
				my = 0;
			}
			else if (
				mx >= menu_x && mx < menu_x + menu_width &&
				my >= menu_y && my < menu_y + menu_height)
			{
				/* pointer is on the meny somewhere not over
				 * an item */
				if (my < menu_y + MST_BORDER_WIDTH(mr))
				{
					/* upper border context (-)*/
					context |= C_SB_TOP;
				}
				else if (
					my >= menu_y + menu_height -
					MST_BORDER_WIDTH(mr))
				{
					/* lower border context (_) */
					context |= C_SB_BOTTOM;
				}
				else if (mx < menu_x + MR_ITEM_X_OFFSET(mr))
				{
					/* left border or left sidepic */
					context |= C_SB_LEFT;
				}
				else if (mx < menu_x + MST_BORDER_WIDTH(mr))
				{
					/* left border context ([)*/
					context |= C_SB_LEFT;
				}
				else if (
					mx >= menu_x + MR_ITEM_X_OFFSET(mr) +
					MR_ITEM_WIDTH(mr))
				{
					/* right sidepic or right border */
					context |= C_SB_RIGHT;
				}
				else if (
					mx >= menu_x + menu_width -
					MST_BORDER_WIDTH(mr))
				{
					/* right border context (])*/
					context |= C_SB_RIGHT;
				}
			}
		}
		else
		{
			mvwm_msg(
				ERR, "menu_shortcuts", "can't get geometry of"
				" menu %s", MR_NAME(mr));
		}
	}

	if (event->type == KeyRelease)
	{
		/* This function is only called with a KeyRelease event if the
		 * user released the 'select' key (s)he configured. */
		pmret->rc = MENU_SELECTED;

		return;
	}

	items_to_move = 0;
	pmret->rc = MENU_NOP;

	/*** handle mouse events ***/
	if (event->type == ButtonRelease)
	{
	        /*** Read the control keys stats ***/
		with_control = event->xbutton.state & ControlMask ? 1 : 0;
		with_shift = event->xbutton.state & ShiftMask ? 1: 0;
		with_meta = event->xbutton.state & Mod1Mask ? 1: 0;
		/** handle menu bindings **/
		binding = menu_binding_is_mouse(event, context);
		if (binding != NULL)
		{
			parse_menu_action(
				mr, binding->Action, &saction, &items_to_move,
				&do_skip_section, &command);
		}
		index = 0;
		ikeychar = 0;
	}
	else /* Should be KeyPressed */
	{
	        /*** Read the control keys stats ***/
		with_control = event->xkey.state & ControlMask? 1 : 0;
		with_shift = event->xkey.state & ShiftMask? 1: 0;
		with_meta = event->xkey.state & Mod1Mask? 1: 0;

		/*** handle double-keypress ***/

		if (pdkp->timestamp &&
		    fev_get_evtime() - pdkp->timestamp <
		    MST_DOUBLE_CLICK_TIME(pmp->menu) &&
		    event->xkey.state == pdkp->keystate &&
		    event->xkey.keycode == pdkp->keycode)
		{
			*pmi_current = NULL;
			pmret->rc = MENU_DOUBLE_CLICKED;

			return;
		}
		pdkp->timestamp = 0;

		/*** find out the key ***/

		/* Is it okay to treat keysym-s as Ascii?
		 * No, because the keypad numbers don't work.
		 * Use XlookupString */
		index = XLookupString(&(event->xkey), &ckeychar, 1, &keysym,
				      NULL);
		ikeychar = (int)ckeychar;
	}
	/*** Try to match hot keys ***/

	/* Need isascii here - isgraph might coredump! */
	if (index == 1 && isascii(ikeychar) && isgraph(ikeychar) &&
	    with_control == 0 && with_meta == 0)
	{
		/* allow any printable character to be a keysym, but be sure
		 * control isn't pressed */
		MenuItem *mi;
		MenuItem *mi1;
		int key;
		int countHotkey = 0;

		/* if this is a letter set it to lower case */
		if (isupper(ikeychar))
		{
			ikeychar = tolower(ikeychar) ;
		}

		/* MMH [email protected] 2/7/99
		 * Multiple hotkeys per menu
		 * Search menu for matching hotkey;
		 * remember how many we found and where we found it */
		mi = (mi_current == NULL || mi_current == MR_LAST_ITEM(mr)) ?
			MR_FIRST_ITEM(mr) : MI_NEXT_ITEM(mi_current);
		mi1 = mi;
		do
		{
			if (MI_HAS_HOTKEY(mi) && !MI_IS_TITLE(mi) &&
			    (!MI_IS_HOTKEY_AUTOMATIC(mi) ||
			     MST_USE_AUTOMATIC_HOTKEYS(mr)))
			{
				key = (MI_LABEL(mi)[(int)MI_HOTKEY_COLUMN(mi)])
					[MI_HOTKEY_COFFSET(mi)];
				key = tolower(key);
				if (ikeychar == key)
				{
					if (++countHotkey == 1)
					{
						new_item = mi;
					}
				}
			}
			mi = (mi == MR_LAST_ITEM(mr)) ?
				MR_FIRST_ITEM(mr) : MI_NEXT_ITEM(mi);
		}
		while (mi != mi1);

		/* For multiple instances of a single hotkey, just move the
		 * selection */
		/* TA:  2011-07-24:  But if the user has turned off
		 * "UniqueHotkeyActivatedImmediate", keep the menu open until
		 * the user has asked for that entry to be enacted.  This also
		 * implies the style "TitleWarpOff" and we're not over a popup
		 * item, in which case the pointer is warped to the submenu in
		 * the usual way.
		 */
		if ((countHotkey > 1) || (countHotkey >=1 && (
					  (!MST_DO_WARP_TO_TITLE(mr) ||
					   !MI_IS_POPUP(new_item))
					  ) &&
					  !MST_HOTKEY_ACTIVATES_IMMEDIATE(mr)))
		{
			*pmi_current = new_item;
			pmret->rc = MENU_NEWITEM;

			return;
		}
		/* Do things the old way for unique hotkeys in the menu */
		else if (countHotkey == 1)
		{
			*pmi_current = new_item;
			if (new_item && MI_IS_POPUP(new_item))
			{
				pmret->rc = MENU_POPUP;
			}
			else
			{
				pmret->rc = MENU_SELECTED;
			}

			return;
		}
		/* MMH [email protected] 2/7/99 */
	}

	/*** now determine the action to take ***/

	/** handle menu key bindings **/
	if (
		event->type == KeyPress && keysym == XK_Escape &&
		with_control == 0 && with_shift == 0 &&
		with_meta == 0)
	{
		/* Don't allow override of Escape with no modifiers */
		saction = SA_ABORT;

	}
	else if (event->type == KeyPress)
	{
		binding = menu_binding_is_key(event, context);
		if (binding != NULL)
		{
			parse_menu_action(
				mr, binding->Action, &saction, &items_to_move,
				&do_skip_section, &command);
		}
	}

	if (
		!mi_current &&
		(saction == SA_ENTER || saction == SA_MOVE_ITEMS ||
		 saction == SA_SELECT || saction == SA_SCROLL))
	{
		if (is_geometry_known)
		{
			if (my < menu_y + MST_BORDER_WIDTH(mr))
			{
				saction = SA_FIRST;
			}
			else if (my > menu_y + menu_height -
				 MST_BORDER_WIDTH(mr))
			{
				saction = SA_LAST;
			}
			else
			{
				saction = SA_WARPBACK;
			}
		}
		else
		{
			saction = SA_FIRST;
		}
	}

	/*** execute the necessary actions ***/

	switch (saction)
	{
	case SA_ENTER:
		if (mi_current && MI_IS_POPUP(mi_current))
		{
			pmret->rc = MENU_POPUP;
		}
		else
		{
			pmret->rc = MENU_NOP;
		}
		break;

	case SA_LEAVE:
		pmret->rc =
			(MR_IS_TEAR_OFF_MENU(mr)) ? MENU_NOP : MENU_POPDOWN;
		break;
	case SA_FIRST:
		if (do_skip_section)
		{
			*pmi_current = get_selectable_item_from_section(
				mr, items_to_move);
		}
		else
		{
			*pmi_current = get_selectable_item_from_index(
				mr, items_to_move);
		}
		if (*pmi_current != NULL)
		{
			pmret->rc = MENU_NEWITEM;
		}
		else
		{
			pmret->rc = MENU_NOP;
		}
		break;
	case SA_LAST:
		if (do_skip_section)
		{
			get_selectable_item_count(mr, &index);
			index += items_to_move;
			if (index < 0)
			{
				index = 0;
			}
			*pmi_current = get_selectable_item_from_section(
				mr, index);
			if (*pmi_current != NULL)
			{
				pmret->rc = MENU_NEWITEM;
			}
			else
			{
				pmret->rc = MENU_NOP;
			}
		}
		else
		{
			index = get_selectable_item_count(mr, NULL);
			if (index > 0)
			{
				index += items_to_move;
				if (index < 0)
				{
					index = 0;
				}
				*pmi_current = get_selectable_item_from_index(
					mr, index);
				pmret->rc = (*pmi_current) ?
					MENU_NEWITEM : MENU_NOP;
			}
			else
			{
				pmret->rc = MENU_NOP;
			}
		}
		break;
	case SA_MOVE_ITEMS:
		if (do_skip_section)
		{
			int section;
			int count;

			get_selectable_item_count(mr, &count);
			get_selectable_item_index(mr, mi_current, &section);
			section += items_to_move;
			if (section < 0)
				section = count;
			else if (section > count)
				section = 0;
			index = section;
		}
		else if (items_to_move < 0)
		{
			index = get_selectable_item_index(
				mr, mi_current, NULL);
			if (index == 0)
				/* wraparound */
				index = get_selectable_item_count(mr, NULL);
			else
			{
				index += items_to_move;
			}
		}
		else
		{
			index = get_selectable_item_index(
				mr, mi_current, NULL) +
				items_to_move;
			/* correct for the case that we're between items */
			if (!MI_IS_SELECTABLE(mi_current))
			{
				index--;
			}
		}
		if (do_skip_section)
		{
			new_item = get_selectable_item_from_section(mr, index);
		}
		else
		{
			new_item = get_selectable_item_from_index(mr, index);
			if (items_to_move > 0 && new_item == mi_current)
			{
				new_item =
					get_selectable_item_from_index(mr, 0);
			}
		}
		if (new_item)
		{
			*pmi_current = new_item;
			pmret->rc = MENU_NEWITEM;
		}
		else
		{
			pmret->rc = MENU_NOP;
		}
		break;
	case SA_CONTINUE:
		*pmi_current = MR_LAST_ITEM(mr);
		if (*pmi_current && MI_IS_POPUP(*pmi_current))
		{
			/* enter the submenu */
			pmret->rc = MENU_POPUP;
		}
		else
		{
			/* do nothing */
			*pmi_current = mi_current;
			pmret->rc = MENU_NOP;
		}
		break;
	case SA_WARPBACK:
		/* Warp the pointer back into the menu. */
		FWarpPointer(
			dpy, 0, MR_WINDOW(mr), 0, 0, 0, 0,
			menudim_middle_x_offset(&MR_DIM(mr)), my - menu_y);
		pmret->rc = MENU_NEWITEM_FIND;
		break;
	case SA_SELECT:
		pmret->rc = MENU_SELECTED;
		return;
	case SA_ABORT:
		pmret->rc =
			(MR_IS_TEAR_OFF_MENU(mr)) ?
			MENU_KILL_TEAR_OFF_MENU : MENU_ABORTED;
		return;
	case SA_TEAROFF:
		pmret->rc =
			(MR_IS_TEAR_OFF_MENU(mr)) ? MENU_NOP : MENU_TEAR_OFF;
		return;
	case SA_SCROLL:
		if (MST_MOUSE_WHEEL(mr) == MMW_MENU)
		{
			items_to_move *= -1;
		}
		if (
			!menu_get_outer_geometry(
				mr, pmp, &JunkRoot, &menu_x, &menu_y,
				&JunkWidth, &menu_height,
				&JunkBW, &JunkDepth))
		{
			mvwm_msg(
				ERR, "menu_shortcuts",
				"can't get geometry of menu %s", MR_NAME(mr));
			return;
		}
		if (do_skip_section)
		{
			int count;

			get_selectable_item_count(mr, &count);
			get_selectable_item_index(mr, mi_current, &index);
			index += items_to_move;
			if (index < 0)
			{
				index = 0;
			}
			else if (index > count)
			{
				index = count;
			}
			new_item = get_selectable_item_from_section(mr, index);
		}
		else
		{
			index = get_selectable_item_index(
				mr, mi_current, NULL);
			if (items_to_move > 0 && !MI_IS_SELECTABLE(mi_current))
			{
				index--;
			}
			index += items_to_move;
			new_item = get_selectable_item_from_index(mr, index);
		}

		if (
			new_item &&
			((items_to_move < 0 &&
			  MI_Y_OFFSET(new_item) > MI_Y_OFFSET(mi_current)) ||
			 (items_to_move > 0 &&
			  MI_Y_OFFSET(new_item) < MI_Y_OFFSET(mi_current))))
		{
			/* never scroll in the "wrong" direction */
			new_item = NULL;
		}

		if (new_item)
		{
			*pmi_current = new_item;
			pmret->rc = MENU_NEWITEM;
			/* Have to work with relative positions or tear off
			 * menus will be hard to reposition */
			if (
				FQueryPointer(
					dpy, MR_WINDOW(mr), &JunkRoot,
					&JunkChild, &JunkX, &JunkY, &mx, &my,
					&JunkMask) ==  0)
			{
				/* This should not happen */
			    	mx = 0;
				my = 0;
			}

			if (MST_MOUSE_WHEEL(mr) == MMW_POINTER)
			{
				if (event->type == ButtonRelease)
				{

				  	FWarpPointer(
						dpy, 0, 0, 0, 0, 0, 0, 0,
						-my +
						menuitem_middle_y_offset(
							new_item,
							MR_STYLE(mr)));
				}
				/* pointer wrapped elsewhere for key events */
			}
			else
			{
				int old_y = menu_y;

				menu_y += my - menuitem_middle_y_offset(
					new_item, MR_STYLE(mr));

				if (
					!MST_SCROLL_OFF_PAGE(mr) &&
					menu_height < MR_SCREEN_HEIGHT(mr))
				{
					if (menu_y < 0)
					{
						FWarpPointer(dpy, 0, 0, 0, 0,
							     0, 0, 0,-menu_y);
						menu_y=0;
					}

					if (
						menu_y + menu_height >
						MR_SCREEN_HEIGHT(mr))
					{
						FWarpPointer(
							dpy, 0, 0, 0, 0, 0, 0,
							0,
							MR_SCREEN_HEIGHT(mr) -
							menu_y - menu_height);
						menu_y = MR_SCREEN_HEIGHT(mr) -
							menu_height;
					}
				}
				if (old_y != menu_y)
				{
					pmret->rc = MENU_NEWITEM_MOVEMENU;
					*ret_menu_x = menu_x;
					*ret_menu_y = menu_y;
				}
				else
				{
					pmret->rc = MENU_NEWITEM;
				}
			}
		}
		else
		{
			pmret->rc = MENU_NOP;
		}
		break;
	case SA_EXEC_CMD:
		pmret->rc = MENU_EXEC_CMD;
		*pmp->ret_paction = command;
		break;
	case SA_NONE:
	default:
		pmret->rc = MENU_NOP;
		break;
	}
	if (saction != SA_SCROLL && pmret->rc == MENU_NEWITEM)
	{
		if (!menu_get_outer_geometry(
			    mr, pmp, &JunkRoot, &menu_x, &menu_y,
			    &JunkWidth, &menu_height,
			    &JunkBW, &JunkDepth))
		{
			mvwm_msg(
				ERR, "menu_shortcuts",
				"can't get geometry of menu %s", MR_NAME(mr));
			return;
		}
		if (menu_y < 0 || menu_y + menu_height > MR_SCREEN_HEIGHT(mr))
		{
			menu_y = (menu_y < 0) ?
				0 : MR_SCREEN_HEIGHT(mr) - menu_height;
			pmret->rc = MENU_NEWITEM_MOVEMENU;
			*ret_menu_x = menu_x;
			*ret_menu_y = menu_y;
		}
	}

	return;
}
示例#6
0
文件: TextField.c 项目: fvwmorg/fvwm
void EvtMouseTextField(struct XObj *xobj,XButtonEvent *EvtButton)
{
	unsigned int modif;
	int x1,x2,y1,y2,i;
	Window Win1,Win2;
	int PosCurs=0;
	int SizeBuf;
	char *str;
	int NewPos;
	Atom type;
	XEvent event;
	int ButPress=1;
	int format;
	unsigned long longueur,octets_restant;
	unsigned char *donnees=(unsigned char *)"";
	XRectangle rect;
	int start_pos, selection_pos, curs_pos;

	/* On deplace le curseur a la position de la souris */
	/* On recupere la position de la souris */
	/* We move the cursor at mouse position and we get the mouse position
	 */
	switch (EvtButton->button)
	{
	case Button1:
		FQueryPointer(
			dpy,*xobj->ParentWin,&Win1,&Win2,&x1,&y1,&x2,&y2,
			&modif);
		x2=x2-xobj->x;
		/* see where we clicked */
		PosCurs=0;
		/* byte position of first visible character */
		start_pos = getByteOffsetBoundsCheck(xobj->Ffont, xobj->title,
						     xobj->value3);
		/* cursor offset in bytes */
		curs_pos = 0;
		while ((curs_pos < strlen(xobj->title + start_pos)) &&
		       (x2 > FlocaleTextWidth(
				    xobj->Ffont,xobj->title + start_pos,
				    curs_pos) + 8))
		{
			curs_pos += FlocaleStringNumberOfBytes(
					  xobj->Ffont,
					  xobj->title + start_pos + curs_pos);
			PosCurs++;
		}
		DrawPointTxt(xobj,xobj->TabColor[back]);
		/* set selection start and end where clicked */
		/* first visible char + position clicked */
		xobj->value = PosCurs + xobj->value3;
		xobj->value2 = PosCurs + xobj->value3;
		/* byte offset corresponding to the above */
		start_pos = getByteOffsetBoundsCheck(xobj->Ffont, xobj->title,
						     xobj->value3);
		selection_pos = getByteOffsetBoundsCheck(xobj->Ffont,
							 xobj->title,
							 xobj->value3);
		DrawPointTxt(xobj,xobj->TabColor[fore]);
		DrawTextField(xobj,NULL);

		while (ButPress)
		{
			FNextEvent(dpy, &event);
			switch (event.type)
			{
			case MotionNotify:
				FQueryPointer(
					dpy,*xobj->ParentWin,&Win1,&Win2,&x1,
					&y1,&x2,&y2,&modif);
				x2=x2-xobj->x;
				PosCurs=0;
				curs_pos = 0;
				/* determine how far in the mouse is now */
				while ((curs_pos < strlen(
						xobj->title + start_pos)) &&
				       (x2 >
					FlocaleTextWidth(
						xobj->Ffont,xobj->title+
						start_pos, curs_pos) + 8))
				{
					curs_pos += FlocaleStringNumberOfBytes(
							   xobj->Ffont,
							   xobj->title +
							   start_pos +
							   curs_pos);
					PosCurs++;
				}
				/* Limitation de la zone de dessin */
				/* limitation of the drawing zone */
				/* these 2 if-statements updates current
				   cursor position of the widget if needed */
				if (PosCurs > (xobj->value2 - xobj->value3))
				{
					/* select made "forward" */
					rect.x=
						FlocaleTextWidth(
							xobj->Ffont,
							xobj->title+
							start_pos,
							selection_pos -
							start_pos);
					rect.y=0;
					rect.width=
						FlocaleTextWidth(
							xobj->Ffont,
							xobj->title+
							start_pos,
							curs_pos)
						-rect.x+1;
					rect.height=xobj->height;
					xobj->value2 = PosCurs + xobj->value3;
					DrawTextField(xobj,NULL);
				}
				else if (PosCurs <
					 (xobj->value2 - xobj->value3))
				{
					/* selection made "backwards" */
					rect.x=FlocaleTextWidth(
						xobj->Ffont,
						xobj->title+
						start_pos,
						curs_pos) - 1;
					rect.y=0;
					rect.width=FlocaleTextWidth(
						xobj->Ffont,
						xobj->title+
						start_pos,
						selection_pos - start_pos) -
						rect.x+2;
					rect.height=xobj->height;
					xobj->value2= PosCurs + xobj->value3;
					DrawTextField(xobj,NULL);
				}

				break;
			case ButtonRelease:
				ButPress=0;
				break;
			}
		}

		/* Enregistrement de la selection dans le presse papier */
		/* Le programme devient proprietaire de la selection */
		/* selection stuff: get the selection */
		if (xobj->value != xobj->value2)
		{
			str=(char*)GetText(xobj, xobj->value2);
			for (i=0;i<=7;i++)
				XStoreBuffer(dpy,str,strlen(str),i);
			Scrapt = (char*)realloc(
					(void*)Scrapt,
					(strlen(str)+2)*sizeof(char));
			Scrapt = strcpy(Scrapt,str);
			free(str);
			x11base->HaveXSelection=True;
			XSetSelectionOwner(
				dpy,XA_PRIMARY,x11base->win,EvtButton->time);
			SelectOneTextField(xobj);
		}
		break;

	case Button2:                        /* Colle le texte */
		/* Si l'application possede pas la selection, elle la demande
		 */
		/* sinon elle lit son presse papier */
		/* read the selection */
		if (!x11base->HaveXSelection)
		{
			/* Demande de la selection */
			/* ask for the selection */
			XConvertSelection(
				dpy,XA_PRIMARY,XA_STRING,propriete,
				*xobj->ParentWin, EvtButton->time);
			while (!(FCheckTypedEvent(dpy,SelectionNotify,&event)))
				;
			if (event.xselection.property!=None)
				if (event.xselection.selection==XA_PRIMARY)
				{
					XGetWindowProperty(
						dpy,event.xselection.requestor,
						event.xselection.property,0L,
						8192L,False,
						event.xselection.target,&type,
						&format, &longueur,
						&octets_restant,&donnees);
					if (longueur>0)
					{
						Scrapt=(char*)realloc(
							(void*)Scrapt,
							(longueur+1)*
							sizeof(char));
						Scrapt=strcpy(
							Scrapt,(char *)donnees);
						XDeleteProperty(
							dpy, event.xselection.
							requestor,
							event.xselection.
							property);
						XFree(donnees);
					}
				}
		}
		SizeBuf=strlen(Scrapt);
		if (SizeBuf>0)
		{
			NewPos=InsertText(xobj,Scrapt,SizeBuf);
			DrawPointTxt(xobj,xobj->TabColor[back]);
			xobj->value=NewPos;
			xobj->value2=NewPos;
			DrawPointTxt(xobj,xobj->TabColor[fore]);
			DrawTextField(xobj,NULL);
			SendMsg(xobj,SingleClic);
		}
		break;

	case Button3:                /* Appuie sur le troisieme bouton */
		FQueryPointer(
			dpy,*xobj->ParentWin,&Win1,&Win2,&x1,&y1,&x2,&y2,
			&modif);
		x2=x2-xobj->x;
		PosCurs=0;
		while ((PosCurs<strlen(xobj->title))&&
		       (x2>FlocaleTextWidth(
			       xobj->Ffont,xobj->title+xobj->value3,
			       PosCurs)+8))
			PosCurs++;
		if ((PosCurs<xobj->value) && (xobj->value<xobj->value2))
			xobj->value=xobj->value2;
		if ((PosCurs>xobj->value) && (xobj->value>xobj->value2))
			xobj->value=xobj->value2;
		xobj->value2=PosCurs+xobj->value3;
		DrawTextField(xobj,NULL);

		while (ButPress)
		{
			FNextEvent(dpy, &event);
			switch (event.type)
			{
			case MotionNotify:
				FQueryPointer(
					dpy,*xobj->ParentWin,&Win1,&Win2,&x1,
					&y1,&x2,&y2,&modif);
				x2=x2-xobj->x;
				while ((PosCurs<strlen(xobj->title))&&
				       (x2 >
					FlocaleTextWidth(
						xobj->Ffont,
						xobj->title+xobj->value3,
						PosCurs)+8))
					PosCurs++;
				if (PosCurs>xobj->value2)
				{
					rect.x=
						FlocaleTextWidth(
							xobj->Ffont,
							xobj->title+
							xobj->value3,
							xobj->value2);
					rect.y=0;
					rect.width=
						FlocaleTextWidth(
							xobj->Ffont,
							xobj->title+
							xobj->value3,PosCurs+1)
						-rect.x+1;
					rect.height=xobj->height;
					xobj->value2=PosCurs;
					DrawTextField(xobj,NULL);
				}
				else
					if (PosCurs<xobj->value2)
					{
						rect.x=FlocaleTextWidth(
							xobj->Ffont,
							xobj->title+
							xobj->value3,
							PosCurs)-1;
						rect.y=0;
						rect.width=FlocaleTextWidth(
							xobj->Ffont,
							xobj->title+xobj->
							value3,
							xobj->value2+1)-
							rect.x+2;
						rect.height=xobj->height;
						xobj->value2=
							PosCurs+xobj->value3;
						DrawTextField(xobj,NULL);
					}
				PosCurs=0;
				break;
			case ButtonRelease:
				ButPress=0;
				break;
			}
		}
		if (xobj->value!=xobj->value2)
		{
			str=(char*)GetText(xobj,xobj->value2);
			for (i=0;i<=7;i++)
				XStoreBuffer(dpy,str,strlen(str),i);
			Scrapt=(char*)realloc(
				(void*)Scrapt,(strlen(str)+2)*sizeof(char));
			Scrapt=strcpy(Scrapt,str);
			free(str);
			x11base->HaveXSelection=True;
			XSetSelectionOwner(
				dpy,XA_PRIMARY,x11base->win,EvtButton->time);
		}
		break;
	}
}
示例#7
0
文件: PushButton.c 项目: fvwmorg/fvwm
void EvtMousePushButton(struct XObj *xobj, XButtonEvent *EvtButton)
{
	static XEvent event;
	int End = 1;
	unsigned int modif;
	int x1,x2,y1,y2,i;
	Window Win1,Win2,WinPop;
	Window WinBut = 0;
	int In = 0;
	char *str;
	int x,y,hOpt,yMenu,hMenu,wMenu;
	int oldvalue = 0,newvalue;
	unsigned long mask;
	XSetWindowAttributes Attr;

	if (EvtButton->button == Button1)
	{
		i = (xobj->width -
		     FlocaleTextWidth(
			     xobj->Ffont, xobj->title, strlen(xobj->title)))/2;

		while (End)
		{
			FNextEvent(dpy, &event);
			switch (event.type)
			{
			case EnterNotify:
				FQueryPointer(
					dpy, *xobj->ParentWin,
					&Win1, &Win2, &x1, &y1, &x2, &y2,
					&modif);
				if (WinBut == 0)
				{
					WinBut = Win2;
					DrawReliefRect(
						0, 0, xobj->width,
						xobj->height, xobj, shad,
						hili);
					DrawIconStr(
						0,xobj, True,
						PUSH_BUTTON_LCR_OFFSETS, NULL,
						NULL, NULL);
					In = 1;
				}
				else
				{
					if (Win2 == WinBut)
					{
						DrawReliefRect(
							0, 0, xobj->width,
							xobj->height, xobj,
							shad, hili);
						DrawIconStr(
							1, xobj, True,
							PUSH_BUTTON_LCR_OFFSETS,
							NULL, NULL, NULL);
						In = 1;
					}
					else if (In)
					{
						In = 0;
						DrawReliefRect(
							0, 0, xobj->width,
							xobj->height, xobj,
							hili, shad);
						DrawIconStr(
							0, xobj, True,
							PUSH_BUTTON_LCR_OFFSETS,
							NULL, NULL, NULL);
					}
				}
				break;
			case LeaveNotify:
				FQueryPointer(
					dpy, *xobj->ParentWin,
					&Win1, &Win2, &x1, &y1, &x2, &y2,
					&modif);
				if (Win2 == WinBut)
				{
					In = 1;
					DrawReliefRect(
						0, 0, xobj->width,
						xobj->height, xobj, shad,
						hili);
					DrawIconStr(
						1, xobj, True,
						PUSH_BUTTON_LCR_OFFSETS, NULL,
						NULL, NULL);
				}
				else if (In)
				{
					DrawReliefRect(
						0, 0, xobj->width,
						xobj->height, xobj, hili,
						shad);
					DrawIconStr(
						0, xobj, True,
						PUSH_BUTTON_LCR_OFFSETS, NULL,
						NULL, NULL);
					In = 0;
				}
				break;
			case ButtonRelease:
				End = 0;
				DrawReliefRect(
					0, 0, xobj->width, xobj->height, xobj,
					hili, shad);
				DrawIconStr(
					0, xobj, True,
					PUSH_BUTTON_LCR_OFFSETS, NULL, NULL,
					NULL);
				if (In)
				{
					/* Envoie d'un message vide de type
					 * SingleClic pour un clique souris */
					xobj->value = 1;
					SendMsg(xobj, SingleClic);
					xobj->value = 0;
				}
				break;
			}
		}
	}
	/* affichage du popup menu / Drawing the popup menu */
	else if (EvtButton->button == Button3)
	{
		if (xobj->value3 > 1)
		{
			hOpt = xobj->Ffont->height + 10;
			/* Hauteur totale du menu / Total height of the menu */
			hMenu = (xobj->value3 - 1) * hOpt;
			yMenu = xobj->y + xobj->height;
			wMenu = 0;
			for (i = 2 ; i <= xobj->value3; i++)
			{
				str = (char*)GetMenuTitle(xobj->title, i);
				if (wMenu < FlocaleTextWidth(
					    xobj->Ffont, str, strlen(str))+34)
					wMenu = FlocaleTextWidth(
						xobj->Ffont, str,
						strlen(str))+34;
				free(str);
			}

			/* Creation de la fenetre menu / create the menu
			 * window */
			XTranslateCoordinates(dpy, *xobj->ParentWin, Root,
					      xobj->x, yMenu, &x, &y, &Win1);
			if (x<0) x = 0;
			if (y<0) y = 0;
			if (x + wMenu > XDisplayWidth(dpy, screen))
			{
				x = XDisplayWidth(dpy, screen) - wMenu;
			}
			if (y + hMenu > XDisplayHeight(dpy, screen))
			{
				y = y-hMenu-xobj->height;
			}

			mask = 0;
			Attr.background_pixel = xobj->TabColor[back];
			mask |= CWBackPixel;
			Attr.border_pixel  =  0;
			mask |= CWBorderPixel;
			Attr.colormap = Pcmap;
			mask |= CWColormap;
			Attr.cursor = XCreateFontCursor(dpy, XC_hand2);
			mask |= CWCursor;         /* Curseur pour la fenetre */
			Attr.override_redirect = True;
			mask |= CWOverrideRedirect;
			WinPop = XCreateWindow(
				dpy, Root, x, y, wMenu-5, hMenu, 0,
				Pdepth, InputOutput, Pvisual, mask, &Attr);
			if (xobj->colorset >= 0)
				SetWindowBackground(
					dpy, WinPop, wMenu - 5, hMenu,
					&Colorset[xobj->colorset], Pdepth,
					xobj->gc, True);
			XMapRaised(dpy, WinPop);

			/* Dessin du menu */
			DrawPMenu(xobj, WinPop, hOpt, 1);
			do
			{
				FQueryPointer(
					dpy, Root, &Win1, &Win2, &x1, &y1,
					&x2, &y2, &modif);
				/* Determiner l'option courante / Current
				 * option */
				y2 = y2 - y;
				x2 = x2 - x;
				{
					/* calcule de xobj->value / Compute
					 * xobj->value */
					if ((x2 > 0) && (x2 < wMenu) &&
					    (y2 > 0) && (y2 < hMenu))
						newvalue = y2 / hOpt+1;
					else
						newvalue = 0;
					if (newvalue!=oldvalue)
					{
						UnselectMenu(
							xobj, WinPop, hOpt,
							oldvalue, wMenu-5,
							xobj->Ffont->ascent,
							1);
						SelectMenu(
							xobj, WinPop, hOpt,
							newvalue);
						oldvalue = newvalue;
					}
				}
			}
			while (!FCheckTypedEvent(dpy, ButtonRelease, &event));
			XDestroyWindow(dpy, WinPop);
			if (newvalue != 0)
			{
				xobj->value = newvalue;
				SendMsg(xobj, SingleClic);
				xobj->value = 0;
			}
			xobj->DrawObj(xobj, NULL);
		} /* xobj->value3 > 1 */
	} /* EvtButton->button == Button3 */
}