Пример #1
0
Bool get_title_button_geometry(
	FvwmWindow *fw, rectangle *ret_g, int context)
{
	int bnum;

	if (context & C_TITLE)
	{
		ret_g->width = 0;
		ret_g->height = 0;
		get_title_geometry(fw, ret_g);
		ret_g->x += fw->g.frame.x;
		ret_g->y += fw->g.frame.y;

		return True;

	}
	bnum = get_button_number(context);
	if (bnum < 0 || FW_W_BUTTON(fw, bnum) == None)
	{
		return False;
	}
	if (XGetGeometry(
		dpy, FW_W_BUTTON(fw, bnum), &JunkRoot, &ret_g->x, &ret_g->y,
		(unsigned int*)&ret_g->width, (unsigned int*)&ret_g->height,
		(unsigned int*)&JunkBW, (unsigned int*)&JunkDepth) == 0)
	{
		return False;
	}
	XTranslateCoordinates(
		dpy, FW_W_FRAME(fw), Scr.Root, ret_g->x, ret_g->y, &ret_g->x,
		&ret_g->y, &JunkChild);

	return True;
}
Пример #2
0
void broadcast_icon_geometry(
	FvwmWindow *fw, Bool do_force)
{
	rectangle g;
	Bool rc;

	rc = get_visible_icon_geometry(fw, &g);
	if (rc == True && (!IS_ICON_UNMAPPED(fw) || do_force == True))
	{
		BroadcastPacket(
			M_ICON_LOCATION, 7, (long)FW_W(fw),
			(long)FW_W_FRAME(fw), (unsigned long)fw,
			(long)g.x, (long)g.y, (long)g.width, (long)g.height);
	}

	return;
}
Пример #3
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)));
		}
Пример #4
0
/*
 * Defer the execution of a function to the next button press if the context is
 * C_ROOT
 *
 *  Inputs:
 *      cursor  - the cursor to display while waiting
 */
static Bool DeferExecution(
	exec_context_changes_t *ret_ecc, exec_context_change_mask_t *ret_mask,
	cursor_t cursor, int trigger_evtype, int do_allow_unmanaged)
{
	int done;
	int finished = 0;
	int just_waiting_for_finish = 0;
	Window dummy;
	Window original_w;
	static XEvent e;
	Window w;
	int wcontext;
	FvwmWindow *fw;
	int FinishEvent;

	fw = ret_ecc->w.fw;
	w = ret_ecc->w.w;
	original_w = w;
	wcontext = ret_ecc->w.wcontext;
	FinishEvent = ((fw != NULL) ? ButtonRelease : ButtonPress);
	if (wcontext == C_UNMANAGED && do_allow_unmanaged)
	{
		return False;
	}
	if (wcontext != C_ROOT && wcontext != C_NO_CONTEXT && fw != NULL &&
	    wcontext != C_EWMH_DESKTOP)
	{
		if (FinishEvent == ButtonPress ||
		    (FinishEvent == ButtonRelease &&
		     trigger_evtype != ButtonPress))
		{
			return False;
		}
		else if (FinishEvent == ButtonRelease)
		{
			/* We are only waiting until the user releases the
			 * button. Do not change the cursor. */
			cursor = CRS_NONE;
			just_waiting_for_finish = 1;
		}
	}
	if (Scr.flags.are_functions_silent)
	{
		return True;
	}
	if (!GrabEm(cursor, GRAB_NORMAL))
	{
		XBell(dpy, 0);
		return True;
	}
	MyXGrabKeyboard(dpy);
	while (!finished)
	{
		done = 0;
		/* block until there is an event */
		FMaskEvent(
			dpy, ButtonPressMask | ButtonReleaseMask |
			ExposureMask | KeyPressMask | VisibilityChangeMask |
			ButtonMotionMask | PointerMotionMask
			/* | EnterWindowMask | LeaveWindowMask*/, &e);

		if (e.type == KeyPress)
		{
			KeySym keysym = XLookupKeysym(&e.xkey, 0);
			if (keysym == XK_Escape)
			{
				ret_ecc->x.etrigger = &e;
				*ret_mask |= ECC_ETRIGGER;
				UngrabEm(GRAB_NORMAL);
				MyXUngrabKeyboard(dpy);
				return True;
			}
			Keyboard_shortcuts(&e, NULL, NULL, NULL, FinishEvent);
		}
		if (e.type == FinishEvent)
		{
			finished = 1;
		}
		switch (e.type)
		{
		case KeyPress:
		case ButtonPress:
			if (e.type != FinishEvent)
			{
				original_w = e.xany.window;
			}
			done = 1;
			break;
		case ButtonRelease:
			done = 1;
			break;
		default:
			break;
		}
		if (!done)
		{
			dispatch_event(&e);
		}
	}
	MyXUngrabKeyboard(dpy);
	UngrabEm(GRAB_NORMAL);
	if (just_waiting_for_finish)
	{
		return False;
	}
	w = e.xany.window;
	ret_ecc->x.etrigger = &e;
	*ret_mask |= ECC_ETRIGGER | ECC_W | ECC_WCONTEXT;
	if ((w == Scr.Root || w == Scr.NoFocusWin) &&
	    e.xbutton.subwindow != None)
	{
		w = e.xbutton.subwindow;
		e.xany.window = w;
	}
	if (w == Scr.Root || IS_EWMH_DESKTOP(w))
	{
		ret_ecc->w.w = w;
		ret_ecc->w.wcontext = C_ROOT;
		XBell(dpy, 0);
		return True;
	}
	*ret_mask |= ECC_FW;
	if (XFindContext(dpy, w, FvwmContext, (caddr_t *)&fw) == XCNOENT)
	{
		ret_ecc->w.fw = NULL;
		ret_ecc->w.w = w;
		ret_ecc->w.wcontext = C_ROOT;
		XBell(dpy, 0);
		return (True);
	}
	if (w == FW_W_PARENT(fw))
	{
		w = FW_W(fw);
	}
	if (original_w == FW_W_PARENT(fw))
	{
		original_w = FW_W(fw);
	}
	/* this ugly mess attempts to ensure that the release and press
	 * are in the same window. */
	if (w != original_w && original_w != Scr.Root &&
	    original_w != None && original_w != Scr.NoFocusWin &&
	    !IS_EWMH_DESKTOP(original_w))
	{
		if (w != FW_W_FRAME(fw) || original_w != FW_W(fw))
		{
			ret_ecc->w.fw = fw;
			ret_ecc->w.w = w;
			ret_ecc->w.wcontext = C_ROOT;
			XBell(dpy, 0);
			return True;
		}
	}

	if (IS_EWMH_DESKTOP(FW_W(fw)))
	{
		ret_ecc->w.fw = fw;
		ret_ecc->w.w = w;
		ret_ecc->w.wcontext = C_ROOT;
		XBell(dpy, 0);
		return True;
	}
	wcontext = GetContext(NULL, fw, &e, &dummy);
	ret_ecc->w.fw = fw;
	ret_ecc->w.w = w;
	ret_ecc->w.wcontext = C_ROOT;

	return False;
}