Example #1
0
/*
 *
 * Reads the property MOTIF_WM_HINTS
 *
 */
void GetMwmHints(FvwmWindow *t)
{
	int actual_format;
	Atom actual_type;
	unsigned long nitems, bytesafter;

	if (t->mwm_hints)
	{
		XFree((char *)t->mwm_hints);
		t->mwm_hints = NULL;
	}
	if (XGetWindowProperty(
		    dpy, FW_W(t), _XA_MwmAtom, 0L, 32L, False,
		    _XA_MwmAtom, &actual_type, &actual_format, &nitems,
		    &bytesafter,(unsigned char **)&t->mwm_hints)==Success)
	{
		if (nitems >= PROP_MOTIF_WM_HINTS_ELEMENTS)
		{
			return;
		}
	}

	t->mwm_hints = NULL;

	return;
}
Example #2
0
File: focus.c Project: fvwmorg/fvwm
/* This function is part of a hack to make focus handling work better with
 * applications that use the passive focus model but manage focus in their own
 * sub windows and should thus use the locally active focus model instead.
 * There are many examples like netscape or ddd. */
void focus_force_refresh_focus(const FvwmWindow *fw)
{
	XWindowAttributes winattrs;

	MyXGrabServer(dpy);
	if (XGetWindowAttributes(dpy, FW_W(fw), &winattrs))
	{
		XSelectInput(
			dpy, FW_W(fw),
			winattrs.your_event_mask & ~FocusChangeMask);
		FOCUS_SET(FW_W(fw), NULL /* we don't expect an event */);
		XSelectInput(dpy, FW_W(fw), winattrs.your_event_mask);
	}
	MyXUngrabServer(dpy);

	return;
}
Example #3
0
File: focus.c Project: fvwmorg/fvwm
void _ReturnFocusWindow(FvwmWindow *fw)
{
	sftfwin_args_t sf_args;

	memset(&sf_args, 0, sizeof(sf_args));
	sf_args.do_allow_force_broadcast = 1;
	sf_args.is_focus_by_flip_focus_cmd = 0;
	sf_args.do_forbid_warp = 1;
        sf_args.client_entered = 0;
	sf_args.do_force = 0;
	sf_args.set_by = FOCUS_SET_FORCE;
	set_focus_to_fwin(FW_W(fw), fw, &sf_args);

	return;
}
Example #4
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;
}
Example #5
0
File: focus.c Project: fvwmorg/fvwm
/* Takes as input the window that wants the focus and the one that currently
 * has the focus and returns if the new window should get it. */
Bool focus_query_open_grab_focus(FvwmWindow *fw, FvwmWindow *focus_win)
{
	if (fw == NULL)
	{
		return False;
	}
	focus_win = get_focus_window();
	if (focus_win != NULL &&
	    FP_DO_OVERRIDE_GRAB_FOCUS(FW_FOCUS_POLICY(focus_win)))
	{
		/* Don't steal the focus from the current window */
		return False;
	}
	validate_transientfor(fw);
	if (IS_TRANSIENT(fw) && FW_W_TRANSIENTFOR(fw) != Scr.Root)
	{
		if (focus_win != NULL &&
		    FP_DO_GRAB_FOCUS_TRANSIENT(FW_FOCUS_POLICY(fw)) &&
		    FW_W(focus_win) == FW_W_TRANSIENTFOR(fw))
		{
			/* it's a transient and its transientfor currently has
			 * focus. */
			return True;
		}
	}
	else
	{
		if (FP_DO_GRAB_FOCUS(FW_FOCUS_POLICY(fw)) &&
		    (focus_win == NULL ||
		     !FP_DO_OVERRIDE_GRAB_FOCUS(FW_FOCUS_POLICY(focus_win))))
		{
			return True;
		}
	}

	return False;
}
Example #6
0
File: focus.c Project: fvwmorg/fvwm
void _SetFocusWindow(
	FvwmWindow *fw, Bool do_allow_force_broadcast,
	fpol_set_focus_by_t set_by, Bool client_entered)
{
	sftfwin_args_t sf_args;

	memset(&sf_args, 0, sizeof(sf_args));
	sf_args.do_allow_force_broadcast = !!do_allow_force_broadcast;
	sf_args.is_focus_by_flip_focus_cmd = 0;
	sf_args.do_forbid_warp = 0;
	sf_args.do_force = 1;
	sf_args.set_by = set_by;
        if (client_entered)
	{
		sf_args.client_entered = 1;
	}
	else
	{
		sf_args.client_entered = 0;
	}
	set_focus_to_fwin(FW_W(fw), fw, &sf_args);

	return;
}
Example #7
0
static signed int expand_vars_extended(
	char *var_name, char *output, cond_rc_t *cond_rc,
	const exec_context_t *exc)
{
	char *rest;
	char dummy[64] = "\0";
	char *target = (output) ? output : dummy;
	int cs = -1;
	int n;
	int i;
	int l;
	int x;
	int y;
	Pixel pixel = 0;
	int val = -12345678;
	const char *string = NULL;
	char *allocated_string = NULL;
	char *quoted_string = NULL;
	Bool should_quote = False;
	Bool is_numeric = False;
	Bool is_target = False;
	Bool is_x;
	Window context_w = Scr.Root;
	FvwmWindow *fw = exc->w.fw;
	signed int len = -1;

	/* allow partial matches for *.cs, gt, ... etc. variables */
	switch ((i = GetTokenIndex(var_name, partial_function_vars, -1, &rest)))
	{
	case VAR_FG_CS:
	case VAR_BG_CS:
	case VAR_HILIGHT_CS:
	case VAR_SHADOW_CS:
	case VAR_FGSH_CS:
		if (!isdigit(*rest) || (*rest == '0' && *(rest + 1) != 0))
		{
			/* not a non-negative integer without leading zeros */
			return -1;
		}
		if (sscanf(rest, "%d%n", &cs, &n) < 1)
		{
			return -1;
		}
		if (*(rest + n) != 0)
		{
			/* trailing characters */
			return -1;
		}
		if (cs < 0)
		{
			return -1;
		}
		alloc_colorset(cs);
		switch (i)
		{
		case VAR_FG_CS:
			pixel = Colorset[cs].fg;
			break;
		case VAR_BG_CS:
			pixel = Colorset[cs].bg;
			break;
		case VAR_HILIGHT_CS:
			pixel = Colorset[cs].hilite;
			break;
		case VAR_SHADOW_CS:
			pixel = Colorset[cs].shadow;
			break;
		case VAR_FGSH_CS:
			pixel = Colorset[cs].fgsh;
			break;
		}
		is_target = True;
		len = pixel_to_color_string(dpy, Pcmap, pixel, target, False);
		goto GOT_STRING;
	case VAR_GT_:
		if (rest == NULL)
		{
			return -1;
		}
		string = _(rest);
		goto GOT_STRING;
	case VAR_INFOSTORE_:
		if (rest == NULL)
			return -1;

		if ((string = get_metainfo_value(rest)) == NULL)
			return -1;

		goto GOT_STRING;
	case VAR_DESK_NAME:
		if (sscanf(rest, "%d%n", &cs, &n) < 1)
		{
			return -1;
		}
		if (*(rest + n) != 0)
		{
			/* trailing characters */
			return -1;
		}
		string = GetDesktopName(cs);
		if (string == NULL)
		{
			const char *ddn = _("Desk");
			allocated_string = (char *)safemalloc(19 + strlen(ddn));
			sprintf(allocated_string, "%s %i", ddn, cs);
			string = allocated_string;
		}
		goto GOT_STRING;
	default:
		break;
	}

	/* only exact matches for all other variables */
	switch ((i = GetTokenIndex(var_name, function_vars, 0, &rest)))
	{
	case VAR_DESK_N:
		is_numeric = True;
		val = Scr.CurrentDesk;
		break;
	case VAR_DESK_WIDTH:
		is_numeric = True;
		val = Scr.VxMax + Scr.MyDisplayWidth;
		break;
	case VAR_DESK_HEIGHT:
		is_numeric = True;
		val = Scr.VyMax + Scr.MyDisplayHeight;
		break;
	case VAR_DESK_PAGESX:
		is_numeric = True;
		val = (int)(Scr.VxMax / Scr.MyDisplayWidth) + 1;
		break;
	case VAR_DESK_PAGESY:
		is_numeric = True;
		val = (int)(Scr.VyMax / Scr.MyDisplayHeight) + 1;
		break;
	case VAR_VP_X:
		is_numeric = True;
		val = Scr.Vx;
		break;
	case VAR_VP_Y:
		is_numeric = True;
		val = Scr.Vy;
		break;
	case VAR_VP_WIDTH:
		is_numeric = True;
		val = Scr.MyDisplayWidth;
		break;
	case VAR_VP_HEIGHT:
		is_numeric = True;
		val = Scr.MyDisplayHeight;
		break;
	case VAR_WA_HEIGHT:
		is_numeric = True;
		val = Scr.Desktops->ewmh_working_area.height;
		break;
	case VAR_WA_WIDTH:
		is_numeric = True;
		val = Scr.Desktops->ewmh_working_area.width;
		break;
	case VAR_WA_X:
		is_numeric = True;
		val = Scr.Desktops->ewmh_working_area.x;
		break;
	case VAR_WA_Y:
		is_numeric = True;
		val = Scr.Desktops->ewmh_working_area.y;
		break;
	case VAR_DWA_HEIGHT:
		is_numeric = True;
		val = Scr.Desktops->ewmh_dyn_working_area.height;
		break;
	case VAR_DWA_WIDTH:
		is_numeric = True;
		val = Scr.Desktops->ewmh_dyn_working_area.width;
		break;
	case VAR_DWA_X:
		is_numeric = True;
		val = Scr.Desktops->ewmh_dyn_working_area.x;
		break;
	case VAR_DWA_Y:
		is_numeric = True;
		val = Scr.Desktops->ewmh_dyn_working_area.y;
		break;
	case VAR_PAGE_NX:
		is_numeric = True;
		val = (int)(Scr.Vx / Scr.MyDisplayWidth);
		break;
	case VAR_PAGE_NY:
		is_numeric = True;
		val = (int)(Scr.Vy / Scr.MyDisplayHeight);
		break;
	case VAR_W_ID:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			is_target = True;
			sprintf(target, "0x%x", (int)FW_W(fw));
		}
		break;
	case VAR_W_NAME:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			string = fw->name.name;
			should_quote = True;
		}
		break;
	case VAR_W_ICONNAME:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			string = fw->icon_name.name;
			should_quote = True;
		}
		break;
	case VAR_W_ICONFILE:
	case VAR_W_MINIICONFILE:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			char *t;

			t = (i == VAR_W_ICONFILE) ?
				fw->icon_bitmap_file : fw->mini_pixmap_file;
			/* expand the path if possible */
			allocated_string = PictureFindImageFile(t, NULL, R_OK);
			if (allocated_string == NULL)
			{
				string = t;
			}
			else if (USE_SVG && *allocated_string == ':' &&
				 (string = strchr(allocated_string + 1, ':')))
			{
				string++;
			}
			else
			{
				string = allocated_string;
			}
		}
		break;
	case VAR_W_ICONFILE_SVGOPTS:
	case VAR_W_MINIICONFILE_SVGOPTS:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			char *t;

			if (!USE_SVG)
			{
				return -1;
			}
			t = (i == VAR_W_ICONFILE_SVGOPTS) ?
				fw->icon_bitmap_file : fw->mini_pixmap_file;
			/* expand the path if possible */
			allocated_string = PictureFindImageFile(t, NULL, R_OK);
			string = allocated_string;
			if (string && *string == ':' &&
			    (t = strchr(string + 1, ':')))
			{
				*t = 0;
			}
			else
			{
				string = "";
			}
		}
		break;
	case VAR_W_CLASS:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			string = fw->class.res_class;
			should_quote = True;
		}
		break;
	case VAR_W_RESOURCE:
		if (fw && !IS_EWMH_DESKTOP(FW_W(fw)))
		{
			string = fw->class.res_name;
			should_quote = True;
		}
Example #8
0
/*
 *
 * Reads the openlook properties _OL_WIN_ATTR, _OL_DECOR_ADD, _OL_DECOR_DEL
 *
 * _OL_WIN_ATTR - the win_type field is the either the first atom if the
 * property has length three or the second atom if the property has
 * length five.  It can be any of:
 *     _OL_WT_BASE (no changes)
 *     _OL_WT_CMD (no minimize decoration)
 *     _OL_WT_HELP (no minimize, maximize or resize handle decorations)
 *     _OL_WT_NOTICE (no minimize, maximize, system menu, resize handle
 *         or titlebar decorations)
 *     _OL_WT_OTHER (no minimize, maximize, system menu, resize handle
 *         or titlebar decorations)
 * In addition, if the _OL_WIN_ATTR property is in the three atom format
 * or if the type is _OL_WT_OTHER, then the icon name is not displayed
 * (same behavior as olvwm).
 *
 * _OL_DECOR_ADD or _OL_DECOR_DEL - indivdually add or remove minimize
 * button (_OL_DECOR_CLOSE), resize handles (_OL_DECOR_RESIZE), title bar
 * (_OL_DECOR_HEADER), or icon name (_OL_DECOR_ICON_NAME).
 *
 * The documentation for the Open Look hints was taken from "Advanced X
 * Window Application Programming", Eric F. Johnson and Kevin Reichard
 * (M&T Books), and the olvwm source code (available at ftp.x.org in
 * /R5contrib).
 */
void GetOlHints(FvwmWindow *t)
{
	int actual_format;
	Atom actual_type;
	unsigned long nitems, bytesafter;
	Atom *hints;
	int i;
	Atom win_type;

	t->ol_hints = OL_DECOR_ALL;

	if (XGetWindowProperty(
		    dpy, FW_W(t), _XA_OL_WIN_ATTR, 0L, 32L, False,
		    _XA_OL_WIN_ATTR, &actual_type, &actual_format,
		    &nitems, &bytesafter, (unsigned char **)&hints) == Success)
	{
		if (nitems > 0)
		{
			t->ol_hints |= OL_ANY_HINTS;

			if (nitems == 3)
			{
				win_type = hints[0];
			}
			else
			{
				win_type = hints[1];
			}

			/* got this from olvwm and sort of mapped it to
			 * fvwm/MWM hints */
			if (win_type == _XA_OL_WT_BASE)
			{
				t->ol_hints = OL_DECOR_ALL;
			}
			else if (win_type == _XA_OL_WT_CMD)
			{
				t->ol_hints = OL_DECOR_ALL & ~OL_DECOR_CLOSE;
			}
			else if (win_type == _XA_OL_WT_HELP)
			{
				t->ol_hints = OL_DECOR_ALL &
					~(OL_DECOR_CLOSE | OL_DECOR_RESIZEH);
			}
			else if (win_type == _XA_OL_WT_NOTICE)
			{
				t->ol_hints = OL_DECOR_ALL &
					~(OL_DECOR_CLOSE | OL_DECOR_RESIZEH |
					  OL_DECOR_HEADER | OL_DECOR_ICON_NAME);
			}
			else if (win_type == _XA_OL_WT_OTHER)
			{
				t->ol_hints = 0;
			}
			else
			{
				t->ol_hints = OL_DECOR_ALL;
			}

			if (nitems == 3)
			{
				t->ol_hints &= ~OL_DECOR_ICON_NAME;
			}
		}

		if (hints)
		{
			XFree (hints);
		}
	}

	if (XGetWindowProperty(
		    dpy, FW_W(t), _XA_OL_DECOR_ADD, 0L, 32L, False,
		    XA_ATOM, &actual_type, &actual_format, &nitems,
		    &bytesafter,(unsigned char **)&hints)==Success)
	{
		for (i = 0; i < nitems; i++)
		{
			t->ol_hints |= OL_ANY_HINTS;
			if (hints[i] == _XA_OL_DECOR_CLOSE)
			{
				t->ol_hints |= OL_DECOR_CLOSE;
			}
			else if (hints[i] == _XA_OL_DECOR_RESIZE)
			{
				t->ol_hints |= OL_DECOR_RESIZEH;
			}
			else if (hints[i] == _XA_OL_DECOR_HEADER)
			{
				t->ol_hints |= OL_DECOR_HEADER;
			}
			else if (hints[i] == _XA_OL_DECOR_ICON_NAME)
			{
				t->ol_hints |= OL_DECOR_ICON_NAME;
			}
		}
		if (hints)
		{
			XFree (hints);
		}
	}

	if (XGetWindowProperty(
		    dpy, FW_W(t), _XA_OL_DECOR_DEL, 0L, 32L, False,
		    XA_ATOM, &actual_type, &actual_format, &nitems,
		    &bytesafter,(unsigned char **)&hints)==Success)
	{
		for (i = 0; i < nitems; i++)
		{
			t->ol_hints |= OL_ANY_HINTS;
			if (hints[i] == _XA_OL_DECOR_CLOSE)
			{
				t->ol_hints &= ~OL_DECOR_CLOSE;
			}
			else if (hints[i] == _XA_OL_DECOR_RESIZE)
			{
				t->ol_hints &= ~OL_DECOR_RESIZEH;
			}
			else if (hints[i] == _XA_OL_DECOR_HEADER)
			{
				t->ol_hints &= ~OL_DECOR_HEADER;
			}
			else if (hints[i] == _XA_OL_DECOR_ICON_NAME)
			{
				t->ol_hints &= ~OL_DECOR_ICON_NAME;
			}
		}
		if (hints)
		{
			XFree (hints);
		}
	}

	return;
}
Example #9
0
static void __execute_function(
	cond_rc_t *cond_rc, const exec_context_t *exc, char *action,
	FUNC_FLAGS_TYPE exec_flags, char *args[], Bool has_ref_window_moved)
{
	static int func_depth = 0;
	cond_rc_t *func_rc = NULL;
	cond_rc_t dummy_rc;
	Window w;
	int j;
	char *function;
	char *taction;
	char *trash;
	char *trash2;
	char *expaction = NULL;
	char *arguments[11];
	const func_t *bif;
	Bool set_silent;
	Bool must_free_string = False;
	Bool must_free_function = False;
	Bool do_keep_rc = False;
	/* needed to be able to avoid resize to use moved windows for base */
	extern Window PressedW;
	Window dummy_w;

	if (!action)
	{
		return;
	}
	/* ignore whitespace at the beginning of all config lines */
	action = SkipSpaces(action, NULL, 0);
	if (!action || action[0] == 0)
	{
		/* impossibly short command */
		return;
	}
	if (action[0] == '#')
	{
		/* a comment */
		return;
	}

	func_depth++;
	if (func_depth > MAX_FUNCTION_DEPTH)
	{
		fvwm_msg(
			ERR, "__execute_function",
			"Function '%s' called with a depth of %i, "
			"stopping function execution!",
			action, func_depth);
		func_depth--;
		return;
	}
	if (args)
	{
		for (j = 0; j < 11; j++)
		{
			arguments[j] = args[j];
		}
	}
	else
	{
		for (j = 0; j < 11; j++)
		{
			arguments[j] = NULL;
		}
	}

	if (exc->w.fw == NULL || IS_EWMH_DESKTOP(FW_W(exc->w.fw)))
	{
		if (exec_flags & FUNC_IS_UNMANAGED)
		{
			w = exc->w.w;
		}
		else
		{
			w = Scr.Root;
		}
	}
	else
	{
		FvwmWindow *tw;

		w = GetSubwindowFromEvent(dpy, exc->x.elast);
		if (w == None)
		{
			w = exc->x.elast->xany.window;
		}
		tw = NULL;
		if (w != None)
		{
			if (XFindContext(
				 dpy, w, FvwmContext, (caddr_t *)&tw) ==
			    XCNOENT)
			{
				tw = NULL;
			}
		}
		if (w == None || tw != exc->w.fw)
		{
			w = FW_W(exc->w.fw);
		}
	}

	set_silent = False;
	if (action[0] == '-')
	{
		exec_flags |= FUNC_DONT_EXPAND_COMMAND;
		action++;
	}

	taction = action;
	/* parse prefixes */
	trash = PeekToken(taction, &trash2);
	while (trash)
	{
		if (StrEquals(trash, PRE_SILENT))
		{
			if (Scr.flags.are_functions_silent == 0)
			{
				set_silent = 1;
				Scr.flags.are_functions_silent = 1;
			}
			taction = trash2;
			trash = PeekToken(taction, &trash2);
		}
		else if (StrEquals(trash, PRE_KEEPRC))
		{
			do_keep_rc = True;
			taction = trash2;
			trash = PeekToken(taction, &trash2);
		}
		else
		{
			break;
		}
	}
	if (taction == NULL)
	{
		if (set_silent)
		{
			Scr.flags.are_functions_silent = 0;
		}
		func_depth--;
		return;
	}
	if (cond_rc == NULL || do_keep_rc == True)
	{
		condrc_init(&dummy_rc);
		func_rc = &dummy_rc;
	}
	else
	{
		func_rc = cond_rc;
	}

	GetNextToken(taction, &function);
	if (function)
	{
		char *tmp = function;
		function = expand_vars(
			function, arguments, False, False, func_rc, exc);
		free(tmp);
	}
	if (function && function[0] != '*')
	{
#if 1
		/* DV: with this piece of code it is impossible to have a
		 * complex function with embedded whitespace that begins with a
		 * builtin function name, e.g. a function "echo hello". */
		/* DV: ... and without it some of the complex functions will
		 * fail */
		char *tmp = function;

		while (*tmp && !isspace(*tmp))
		{
			tmp++;
		}
		*tmp = 0;
#endif
		bif = find_builtin_function(function);
		must_free_function = True;
	}
	else
	{
		bif = NULL;
		if (function)
		{
			free(function);
		}
		function = "";
	}

	if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor &&
	    (!bif || !(bif->flags & FUNC_DECOR)))
	{
		fvwm_msg(
			ERR, "__execute_function",
			"Command can not be added to a decor; executing"
			" command now: '%s'", action);
	}

	if (!(exec_flags & FUNC_DONT_EXPAND_COMMAND))
	{
		expaction = expand_vars(
			taction, arguments, (bif) ?
			!!(bif->flags & FUNC_ADD_TO) :
			False, (taction[0] == '*'), func_rc, exc);
		if (func_depth <= 1)
		{
			must_free_string = set_repeat_data(
				expaction, REPEAT_COMMAND, bif);
		}
		else
		{
			must_free_string = True;
		}
	}
	else
	{
		expaction = taction;
	}

#ifdef FVWM_COMMAND_LOG
	fvwm_msg(INFO, "LOG", "%c: %s", (char)exc->type, expaction);
#endif

	/* 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 (expaction[0] == '*')
	{
		if (Scr.cur_decor && Scr.cur_decor != &Scr.DefaultDecor)
		{
			fvwm_msg(
				WARN, "__execute_function",
				"Command can not be added to a decor;"
				" executing command now: '%s'", expaction);
		}

		/* process a module config command */
		ModuleConfig(expaction);
	}
	else
	{
		const exec_context_t *exc2;
		exec_context_changes_t ecc;
		exec_context_change_mask_t mask;

		mask = (w != exc->w.w) ? ECC_W : 0;
		ecc.w.fw = exc->w.fw;
		ecc.w.w = w;
		ecc.w.wcontext = exc->w.wcontext;
		if (bif && bif->func_t != F_FUNCTION)
		{
			char *runaction;
			Bool rc = False;

			runaction = SkipNTokens(expaction, 1);
			if ((bif->flags & FUNC_NEEDS_WINDOW) &&
			    !(exec_flags & FUNC_DONT_DEFER))
			{
				rc = DeferExecution(
					&ecc, &mask, bif->cursor,
					exc->x.elast->type,
					(bif->flags & FUNC_ALLOW_UNMANAGED));
			}
			else if ((bif->flags & FUNC_NEEDS_WINDOW) &&
				 !__context_has_window(
					 exc,
					 bif->flags & FUNC_ALLOW_UNMANAGED))
			{
				/* no context window and not allowed to defer,
				 * skip command */
				rc = True;
			}
			if (rc == False)
			{
				exc2 = exc_clone_context(exc, &ecc, mask);
				if (has_ref_window_moved &&
				    (bif->func_t == F_ANIMATED_MOVE ||
				     bif->func_t == F_MOVE ||
				     bif->func_t == F_RESIZE ||
				     bif->func_t == F_RESIZEMOVE ||
				     bif->func_t == F_RESIZE_MAXIMIZE ||
				     bif->func_t == F_RESIZEMOVE_MAXIMIZE))
				{
					dummy_w = PressedW;
					PressedW = None;
					bif->action(func_rc, exc2, runaction);
					PressedW = dummy_w;
				}
				else
				{
					bif->action(func_rc, exc2, runaction);
				}
				exc_destroy_context(exc2);
			}
		}
		else
		{
			Bool desperate = 1;
			char *runaction;

			if (bif)
			{
				/* strip "function" command */
				runaction = SkipNTokens(expaction, 1);
			}
			else
			{
				runaction = expaction;
			}
			exc2 = exc_clone_context(exc, &ecc, mask);
			execute_complex_function(
				func_rc, exc2, runaction, &desperate,
				has_ref_window_moved);
			if (!bif && desperate)
			{
				if (executeModuleDesperate(
					    func_rc, exc, runaction) == NULL &&
				    *function != 0 && !set_silent)
				{
					fvwm_msg(
						ERR, "__execute_function",
						"No such command '%s'",
						function);
				}
			}
			exc_destroy_context(exc2);
		}
	}

	if (set_silent)
	{
		Scr.flags.are_functions_silent = 0;
	}
	if (cond_rc != NULL)
	{
		cond_rc->break_levels = func_rc->break_levels;
	}
	if (must_free_string)
	{
		free(expaction);
	}
	if (must_free_function)
	{
		free(function);
	}
	func_depth--;

	return;
}
Example #10
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;
}
Example #11
0
/*
 * set the visibale window name and icon name
 */
void EWMH_SetVisibleName(FvwmWindow *fw, Bool is_icon_name)
{
	unsigned char *val;
	char *tmp_str;
	FlocaleCharset *fc = NULL;

	if (!FiconvSupport)
	{
		return;
	}

	/* set the ewmh visible name only if it is != wm name */
	if (is_icon_name)
	{
		if ((fw->icon_name_count == 0 ||
		     !USE_INDEXED_ICON_NAME(fw)) &&
		    !HAS_EWMH_WM_ICON_NAME(fw) &&
		    !HAS_EWMH_WM_NAME(fw))
		{
			ewmh_DeleteProperty(
				FW_W(fw), "_NET_WM_ICON_VISIBLE_NAME",
				EWMH_ATOM_LIST_FVWM_WIN);
			return;
		}
		if (IS_ICON_FONT_LOADED(fw) && fw->icon_font != NULL)
		{
			fc = fw->icon_font->str_fc;
		}
		tmp_str = fw->visible_icon_name;
	}
	else
	{
		if ((fw->name_count == 0 ||
		     !USE_INDEXED_WINDOW_NAME(fw)) &&
		    !HAS_EWMH_WM_NAME(fw) && !HAS_EWMH_WM_ICON_NAME(fw))
		{
			ewmh_DeleteProperty(
				FW_W(fw), "_NET_WM_VISIBLE_NAME",
				EWMH_ATOM_LIST_FVWM_WIN);
			return;
		}
		if (IS_WINDOW_FONT_LOADED(fw) && fw->title_font != NULL)
		{
			fc = fw->title_font->str_fc;
		}
		tmp_str = fw->visible_name;
	}

	if (tmp_str == NULL)
	{
		return; /* should never happen */
	}

	val = (unsigned char *)FiconvCharsetToUtf8(
		dpy, fc, tmp_str, strlen(tmp_str));

	if (val == NULL)
	{
		return;
	}

	if (is_icon_name)
	{
		ewmh_ChangeProperty(
			FW_W(fw), "_NET_WM_ICON_VISIBLE_NAME",
			EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)val,
			strlen((char *)val));
	}
	else
	{
		ewmh_ChangeProperty(
			FW_W(fw), "_NET_WM_VISIBLE_NAME",
			EWMH_ATOM_LIST_FVWM_WIN, (unsigned char *)val,
			strlen((char *)val));
	}
	free(val);
}
Example #12
0
int EWMH_WMName(
	FvwmWindow *fw, XEvent *ev, window_style *style, unsigned long any)
{
	int size = 0;
	char *val;
	char *tmp_str;
	FlocaleCharset *fc = NULL;
	int what_changed;

	if (!FiconvSupport)
		return 0;

	val = ewmh_AtomGetByName(
		FW_W(fw), "_NET_WM_NAME",
		EWMH_ATOM_LIST_PROPERTY_NOTIFY, &size);

	if (val == NULL)
	{
		SET_HAS_EWMH_WM_NAME(fw,0);
		return 0;
	}
	if (IS_WINDOW_FONT_LOADED(fw) && fw->title_font != NULL)
	{
		fc = fw->title_font->str_fc;
	}

	tmp_str = (char *)FiconvUtf8ToCharset(
		dpy, fc, (const char *) val, size);
	free(val);
	if (tmp_str == NULL)
	{
		SET_HAS_EWMH_WM_NAME(fw,0);
		return 0;
	}
	if (strlen(tmp_str) > MAX_WINDOW_NAME_LEN)
	{
		tmp_str[MAX_WINDOW_NAME_LEN] = 0;
	}
	SET_HAS_EWMH_WM_NAME(fw, 1);
	if (fw->name.name && strcmp(tmp_str, fw->name.name) == 0)
	{
		/* migo: some apps update their names every second */
		free(tmp_str);
		return 0;
	}

	if (ev != NULL)
	{
		/* client message */
		free_window_names(fw, True, False);
	}

	fw->name.name = tmp_str;

	if (ev == NULL)
	{
		return 1;
	}

	SET_NAME_CHANGED(fw, 1);
	what_changed = 1;
	if (!WAS_ICON_NAME_PROVIDED(fw))
	{
		fw->icon_name = fw->name;
		what_changed |= 2;
	}
	update_window_names(fw, what_changed);

	return 0;
}
Example #13
0
/*
 * Change by PRB ([email protected]), 31/10/93.  Prepend a hot key
 * specifier to each item in the list.  This means allocating the
 * memory for each item (& freeing it) rather than just using the window
 * title directly. */
void CMD_WindowList(F_CMD_ARGS)
{
	struct MenuRoot *mr;
	struct MenuParameters mp;
	char* ret_action = NULL;
	FvwmWindow *t;
	FvwmWindow **windowList;
	FvwmWindow **iconifiedList = NULL;
	int numWindows;
	int ii;
	char tname[128];
	char loc[64];
	char *name=NULL;
	Bool free_name = False;
	int dwidth;
	int dheight;
	char *tlabel;
	int last_desk_done = INT_MIN;
	int last_desk_displayed = INT_MIN;
	int next_desk = 0;
	char *t_hot=NULL;             /* Menu label with hotkey added */
	char scut = '0';              /* Current short cut key */
	char *opts=NULL;
	char *tok=NULL;
	int desk = Scr.CurrentDesk;
	unsigned long flags = SHOW_DEFAULT;
	char *func = NULL;
	char *ffunc = NULL;
	char *tfunc = NULL;
	char *default_action = NULL;
	MenuReturn mret;
	MenuOptions mops;
	int low_layer = 0;  /* show all layers by default */
	int high_layer = INT_MAX;
	int max_label_width = 0;
	int skiplist_mode = 0; /* do not show skiplist by default */
	Bool use_hotkey = True;
	KeyCode old_sor_keycode;
	char sor_default_keyname[8] = { 'M', 'e', 't', 'a', '_', 'L' };
	char *sor_keyname = sor_default_keyname;
	/* Condition vars. */
	Bool use_condition = False;
	Bool current_at_end = False;
	Bool iconified_at_end = False;
	int ic = 0;
	int ij;
	WindowConditionMask mask;
	char *cond_flags;
	Bool first_desk = True;
	Bool empty_menu = True;
	Bool was_get_menu_opts_called = False;
	FvwmWindow * const fw = exc->w.fw;
	const Window w = exc->w.w;
	const exec_context_t *exc2;

	memset(&mops, 0, sizeof(mops));
	memset(&mret, 0, sizeof(MenuReturn));
	/* parse postitioning args - must call this even if no action is given
	 * because it sets the xinerama screen origin */
	if (action && *action)
	{
		/* Look for condition - CreateFlagString returns NULL if no '('
		 * or '[' */
		cond_flags = CreateFlagString(action, &action);
		if (cond_flags)
		{
			/* Create window mask */
			use_condition = True;
			DefaultConditionMask(&mask);

			/* override for Current [] */
			mask.my_flags.use_circulate_hit = 1;
			mask.my_flags.use_circulate_hit_icon = 1;

			CreateConditionMask(cond_flags, &mask);
			free(cond_flags);
		}
		opts = get_menu_options(
			action, w, fw, NULL, NULL, NULL, &mops);
		was_get_menu_opts_called = True;

		/* parse options */
		while (opts && *opts)
		{
			opts = GetNextSimpleOption(opts, &tok);
			if (!tok)
			{
				break;
			}

			if (StrEquals(tok,"NoHotkeys"))
			{
				use_hotkey = False;
			}
			else if (StrEquals(tok,"Function"))
			{
				opts = GetNextSimpleOption(opts, &func);
			}
			else if (StrEquals(tok,"Desk"))
			{
				free(tok);
				opts = GetNextSimpleOption(opts, &tok);
				if (tok)
				{
					desk = atoi(tok);
					flags &= ~SHOW_ALLDESKS;
				}
			}
			else if (StrEquals(tok,"CurrentDesk"))
			{
				desk = Scr.CurrentDesk;
				flags &= ~SHOW_ALLDESKS;
			}
			else if (StrEquals(tok,"NotAlphabetic"))
			{
				flags &= ~SHOW_ALPHABETIC;
			}
			else if (StrEquals(tok,"Alphabetic"))
			{
				flags |= SHOW_ALPHABETIC;
			}
			else if (StrEquals(tok,"SortByClass"))
			{
				flags |= SORT_BYCLASS;
			}
			else if (StrEquals(tok,"SortByResource"))
			{
				flags |= SORT_BYRESOURCE;
			}
			else if (StrEquals(tok,"ReverseOrder"))
			{
				flags |= SORT_REVERSE;
			}
			else if (StrEquals(tok,"CurrentAtEnd"))
			{
				current_at_end = True;
			}
			else if (StrEquals(tok,"IconifiedAtEnd"))
			{
				iconified_at_end = True;
			}
			else if (StrEquals(tok,"NoDeskSort"))
			{
				flags |= NO_DESK_SORT;
			}
			else if (StrEquals(tok,"ShowPage"))
			{
				flags |= SHOW_PAGE_X | SHOW_PAGE_Y;
			}
			else if (StrEquals(tok,"ShowPageX"))
			{
				flags |= SHOW_PAGE_X;
			}
			else if (StrEquals(tok,"ShowPageY"))
			{
				flags |= SHOW_PAGE_Y;
			}
			else if (StrEquals(tok,"ShowScreen"))
			{
				flags |= SHOW_SCREEN;
			}
			else if (StrEquals(tok,"UseIconName"))
			{
				flags |= SHOW_ICONNAME;
			}
			else if (StrEquals(tok,"NoGeometry"))
			{
				flags &= ~SHOW_GEOMETRY;
				flags &= ~SHOW_INFONOTGEO;
			}
			else if (StrEquals(tok,"NoGeometryWithInfo"))
			{
				flags &= ~SHOW_GEOMETRY;
				flags |= SHOW_INFONOTGEO;
			}
			else if (StrEquals(tok,"Geometry"))
			{
				flags |= SHOW_GEOMETRY;
				flags &= ~SHOW_INFONOTGEO;
			}
			else if (StrEquals(tok,"NoIcons"))
			{
				flags &= ~SHOW_ICONIC;
			}
			else if (StrEquals(tok,"Icons"))
			{
				flags |= SHOW_ICONIC;
			}
			else if (StrEquals(tok,"OnlyIcons"))
			{
				flags = SHOW_ICONIC;
			}
			else if (StrEquals(tok,"NoNormal"))
			{
				flags &= ~SHOW_NORMAL;
			}
			else if (StrEquals(tok,"Normal"))
			{
				flags |= SHOW_NORMAL;
			}
			else if (StrEquals(tok,"OnlyNormal"))
			{
				flags = SHOW_NORMAL;
			}
			else if (StrEquals(tok,"NoSticky"))
			{
				flags &= ~(SHOW_STICKY_ACROSS_PAGES);
				flags &= ~(SHOW_STICKY_ACROSS_DESKS);
			}
			else if (StrEquals(tok,"NoStickyPage"))
			{
				flags &= ~(SHOW_STICKY_ACROSS_PAGES);
			}
			else if (StrEquals(tok,"NoStickyDesk"))
			{
				flags &= ~(SHOW_STICKY_ACROSS_DESKS);
			}
			else if (StrEquals(tok,"Sticky"))
			{
				flags |= SHOW_STICKY_ACROSS_PAGES;
				flags |= SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"StickyPage"))
			{
				flags |= SHOW_STICKY_ACROSS_PAGES;
			}
			else if (StrEquals(tok,"StickyDesk"))
			{
				flags |= SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"OnlySticky"))
			{
				flags = SHOW_STICKY_ACROSS_PAGES;
				flags = SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"OnlyStickyPage"))
			{
				flags = SHOW_STICKY_ACROSS_PAGES;
			}
			else if (StrEquals(tok,"OnlyStickyDesk"))
			{
				flags = SHOW_STICKY_ACROSS_DESKS;
			}
			else if (StrEquals(tok,"UseListSkip"))
			{
				/* deprecated as of 02-May-2007 (SS) */
				fprintf(stderr, "UseListSkip is deprecated. Please use \"UseSkipList\".\n");
				skiplist_mode = 1;
			}
			else if (StrEquals(tok,"UseSkipList"))
			{
				skiplist_mode = 1;
			}
			else if (StrEquals(tok,"OnlyListSkip"))
			{
				/* deprecated as of 02-May-2007 (SS) */
				fprintf(stderr, "OnlyListSkip is deprecated. Please use \"OnlySkipList\".\n");
				skiplist_mode = 2;
			}
			else if (StrEquals(tok,"OnlySkipList"))
			{
				skiplist_mode = 2;
			}
			else if (StrEquals(tok,"NoDeskNum"))
			{
				flags |= NO_DESK_NUM;
			}
			else if (StrEquals(tok,"NoLayer"))
			{
				flags |= NO_LAYER;
			}
			else if (StrEquals(tok,"NoCurrentDeskTitle"))
			{
				flags |= NO_CURRENT_DESK_TITLE;
			}
			else if (StrEquals(tok,"TitleForAllDesks"))
			{
				flags |= TITLE_FOR_ALL_DESKS;
			}
			else if (StrEquals(tok,"NoNumInDeskTitle"))
			{
				flags |= NO_NUM_IN_DESK_TITLE;
			}
			/* these are a bit dubious, but we should keep the
			 * OnTop options for compatibility */
			else if (StrEquals(tok, "NoOnTop"))
			{
				if (high_layer >= Scr.TopLayer)
				{
					high_layer = Scr.TopLayer - 1;
				}
			}
			else if (StrEquals(tok, "OnTop"))
			{
				if (high_layer < Scr.TopLayer)
				{
					high_layer = Scr.TopLayer;
				}
			}
			else if (StrEquals(tok, "OnlyOnTop"))
			{
				high_layer = low_layer = Scr.TopLayer;
			}
			else if (StrEquals(tok, "NoOnBottom"))
			{
				if (low_layer <= Scr.BottomLayer)
				{
					low_layer = Scr.BottomLayer - 1;
				}
			}
			else if (StrEquals(tok, "OnBottom"))
			{
				if (low_layer > Scr.BottomLayer)
				{
					low_layer = Scr.BottomLayer;
				}
			}
			else if (StrEquals(tok, "OnlyOnBottom"))
			{
				high_layer = low_layer = Scr.BottomLayer;
			}
			else if (StrEquals(tok, "Layer"))
			{
				free(tok);
				opts = GetNextSimpleOption(opts, &tok);
				if (tok)
				{
					low_layer = high_layer = atoi(tok);
					free(tok);
					opts = GetNextSimpleOption(opts, &tok);
					if (tok)
					{
						high_layer = atoi(tok);
					}
				}
			}
			else if (StrEquals(tok, "SelectOnRelease"))
			{
				if (sor_keyname != sor_default_keyname)
				{
					free(sor_keyname);
				}
				sor_keyname = NULL;
				opts = GetNextSimpleOption(opts, &sor_keyname);
			}
			else if (StrEquals(tok, "MaxLabelWidth"))
			{
				char *wid;

				opts = GetNextSimpleOption(opts, &wid);
				if (wid)
				{
					max_label_width = atoi(wid);
					if (max_label_width < 1)
					{
						max_label_width = 1;
					}
					free(wid);
				}
			}
			else if (!opts || !*opts)
			{
				default_action = safestrdup(tok);
			}
			else
			{
				fvwm_msg(
					ERR, "WindowList","Unknown option '%s'",
					tok);
			}
			if (tok)
			{
				free(tok);
			}
		}
	}
	if (was_get_menu_opts_called == False)
	{
		opts = get_menu_options(
			action, w, fw, NULL, NULL, NULL, &mops);
	}

	tlabel = get_desk_title(desk, flags, True);
	mr = NewMenuRoot(tlabel);
	if (!(flags & NO_CURRENT_DESK_TITLE))
	{
		AddToMenu(mr, tlabel, "TITLE", False, False, False);
		empty_menu = False;
	}
	free(tlabel);

	numWindows = 0;
	for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
	{
		numWindows++;
	}
	windowList = malloc(numWindows*sizeof(t));
	if (windowList == NULL)
	{
		return;
	}
	if (iconified_at_end)
	{
		iconifiedList = malloc(numWindows*sizeof(t));
		if (iconifiedList == NULL)
		{
			free(windowList);
			return;
		}
	}
	/* get the windowlist starting from the current window (if any)*/
	t = get_focus_window();
	if (t == NULL)
	{
		t = Scr.FvwmRoot.next;
	}
	else if (current_at_end)
	{
		if (t->next)
		{
			t = t->next;
		}
		else
		{
			t = Scr.FvwmRoot.next;
		}
	}
	for (ii = 0; ii < numWindows; ii++)
	{
		if (flags & SORT_REVERSE)
		{
			windowList[numWindows - ii - 1] = t;
		}
		else if (iconified_at_end && IS_ICONIFIED(t))
		{
			iconifiedList[ic++] = t;
		}
		else
		{
			windowList[ii - ic] = t;
		}
		if (t->next)
		{
			t = t->next;
		}
		else
		{
			t = Scr.FvwmRoot.next;
		}
	}
	if (iconified_at_end && ic > 0)
	{
		if (current_at_end && ii > ic)
		{
			windowList[numWindows - 1] = windowList[--ii - ic];
		}
		for (ij = 0; ij < ic; ij++)
		{
			windowList[ij + (ii - ic)] = iconifiedList[ij];
		}
	}

	/* Do alphabetic sort */
	if (flags & (SHOW_ALPHABETIC | SORT_BYCLASS | SORT_BYRESOURCE))
	{
		/* This will be compare or compareReverse if a reverse order
		 * is selected. */
		int (*sort)(const FvwmWindow **a, const FvwmWindow **b);

		switch (flags & (SHOW_ALPHABETIC | SHOW_ICONNAME | \
			SORT_BYCLASS | SORT_BYRESOURCE))
		{
		case SHOW_ALPHABETIC:
			compare = visibleCompare;
			break;
		case SHOW_ALPHABETIC | SHOW_ICONNAME:
			compare = iconCompare;
			break;
		/* Sorting based on class name produces an alphabetic
		 * order so the keyword alphabetic is redundant. */
		case SORT_BYCLASS:
		case SORT_BYCLASS | SHOW_ALPHABETIC:
			compare = classCompare;
			break;
		case SORT_BYCLASS | SHOW_ICONNAME:
		case SORT_BYCLASS | SHOW_ICONNAME | SHOW_ALPHABETIC:
			compare = classIconCompare;
			break;
		case SORT_BYRESOURCE:
		case SORT_BYRESOURCE | SORT_BYCLASS:
		case SORT_BYRESOURCE | SORT_BYCLASS | SHOW_ALPHABETIC:
			compare = resourceCompare;
			break;
		case SORT_BYRESOURCE | SHOW_ICONNAME:
		case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS:
		case SORT_BYRESOURCE | SHOW_ICONNAME | SORT_BYCLASS | \
		SHOW_ALPHABETIC:
			compare = resourceIconCompare;
			break;

		/* All current cases are covered, but if something
		 * changes in the future we leave compare valid even if
		 * it isn't what is expected. */
		default:
			compare = visibleCompare;
			break;
		}

		if ( flags & SORT_REVERSE )
		{
			sort = compareReverse;
		}
		else
		{
			sort = compare;
		}
		qsort(windowList, numWindows, sizeof(t),
		      (int(*)(const void*, const void*))sort);
	}

	while(next_desk != INT_MAX)
	{
		/* Sort window list by desktop number */
		if ((flags & SHOW_ALLDESKS) && !(flags & NO_DESK_SORT))
		{
			/* run through the windowlist finding the first desk
			 * not already processed */
			next_desk = INT_MAX;
			for (ii = 0; ii < numWindows; ii++)
			{
				t = windowList[ii];
				if (t->Desk >last_desk_done &&
				    t->Desk < next_desk)
				{
					next_desk = t->Desk;
				}
			}
		}
		if (!(flags & SHOW_ALLDESKS))
		{
			/* if only doing one desk and it hasn't been done */
			if (last_desk_done  == INT_MIN)
				next_desk = desk; /* select the desk */
			else
				next_desk = INT_MAX; /* flag completion */
		}
		if (flags & NO_DESK_SORT)
			next_desk = INT_MAX; /* only go through loop once */

		last_desk_done = next_desk;
		for (ii = 0; ii < numWindows; ii++)
		{
			t = windowList[ii];
			if (t->Desk != next_desk && !(flags & NO_DESK_SORT))
			{
				continue;
			}
			if (skiplist_mode == 0 && DO_SKIP_WINDOW_LIST(t))
			{
				/* don't want skiplist windows - skip */
				continue;
			}
			if (skiplist_mode == 2 && !DO_SKIP_WINDOW_LIST(t))
			{
				/* don't want no skiplist one - skip */
				continue;
			}
			if (use_condition && !MatchesConditionMask(t, &mask))
			{
				/* doesn't match specified condition */
				continue;
			}
			if (!(flags & SHOW_ICONIC) && (IS_ICONIFIED(t)))
			{
				/* don't want icons - skip */
				continue;
			}
			if (!(flags & SHOW_STICKY_ACROSS_PAGES) &&
			    (IS_STICKY_ACROSS_PAGES(t)))
			{
				/* don't want sticky ones - skip */
				continue;
			}
			if (!(flags & SHOW_STICKY_ACROSS_DESKS) &&
			    (IS_STICKY_ACROSS_DESKS(t)))
			{
				/* don't want sticky ones - skip */
				continue;
			}
			if (!(flags & SHOW_NORMAL) &&
			    !(IS_ICONIFIED(t) ||
			      IS_STICKY_ACROSS_PAGES(t) ||
			      IS_STICKY_ACROSS_DESKS(t)))
			{
				/* don't want "normal" ones - skip */
				continue;
			}
			if (get_layer(t) < low_layer ||
			    get_layer(t) > high_layer)
			{
				/* don't want this layer */
				continue;
			}

			empty_menu = False;
			/* add separator between desks when geometry
			 * shown but not at the top*/
			if (t->Desk != last_desk_displayed)
			{
				if (last_desk_displayed != INT_MIN)
				{
					if (((flags & SHOW_GEOMETRY) ||
					     (flags & SHOW_INFONOTGEO)) &&
					    !(flags & TITLE_FOR_ALL_DESKS))
					{
						AddToMenu(
							mr, NULL, NULL, False,
							False, False);
					}
					if (flags & TITLE_FOR_ALL_DESKS)
					{
						tlabel = get_desk_title(
							t->Desk, flags, False);
						AddToMenu(
							mr, tlabel, "TITLE",
							False, False, False);
						free(tlabel);
					}
				}
				last_desk_displayed = t->Desk;
			}
			if (first_desk && flags & TITLE_FOR_ALL_DESKS)
			{
				tlabel = get_desk_title(t->Desk, flags, False);
				AddToMenu(
					mr, tlabel, "TITLE", False, False,
					False);
				free(tlabel);
			}
			first_desk = False;

			if (flags & SHOW_ICONNAME)
			{
				name = t->visible_icon_name;
			}
			else
			{
				name = t->visible_name;
			}

			free_name = False;
			if (!name)
			{
				name = "NULL_NAME";
			}
			else if (max_label_width > 0 &&
				 strlen(name) > max_label_width)
			{
				name = strdup(name);
				name[max_label_width] = '\0';
				free_name = True;
			}

			t_hot = safemalloc(strlen(name) + 80);
			if (use_hotkey)
			{
				/* Generate label */
				sprintf(t_hot, "&%c. ", scut);
			}
			else
			{
				*t_hot = 0;
			}
			if (!(flags & SHOW_INFONOTGEO))
			{
				strcat(t_hot, name);
			}
			if (*t_hot == 0)
			{
				strcpy(t_hot, " ");
			}

			/* Next shortcut key */
			if (scut == '9')
			{
				scut = 'A';
			}
			else if (scut == 'Z')
			{
				scut = '0';
			}
			else
			{
				scut++;
			}

			if (flags & SHOW_INFONOTGEO)
			{
				tname[0]=0;
				if (!IS_ICONIFIED(t) &&
				    !(flags & NO_DESK_NUM))
				{
					sprintf(loc,"%d:", t->Desk);
					strcat(tname,loc);
				}
				if (IS_ICONIFIED(t))
				{
					strcat(tname, "(");
				}
				strcat(t_hot,"\t");
				strcat(t_hot,tname);
				strcat(t_hot, name);
				if (IS_ICONIFIED(t))
				{
					strcat(t_hot, ")");
				}
			}
			else if (flags & SHOW_GEOMETRY)
			{
				size_borders b;

				tname[0]=0;
				if (IS_ICONIFIED(t))
				{
					strcpy(tname, "(");
				}
				if (!(flags & NO_DESK_NUM))
				{
					sprintf(loc, "%d", t->Desk);
					strcat(tname, loc);
				}
				if (flags & SHOW_SCREEN)
				{
					fscreen_scr_arg fscr;
					int scr;

					fscr.xypos.x =
						Scr.Vx + t->g.frame.x +
						t->g.frame.width / 2;
					fscr.xypos.y =
						Scr.Vy + t->g.frame.y +
						t->g.frame.height / 2;
					scr = FScreenGetScrId(
						&fscr, FSCREEN_XYPOS);
					sprintf(loc, "@%d", scr);
					strcat(tname, loc);
				}
				if (flags & SHOW_PAGE_X)
				{
					sprintf(loc, "+%d",
						(Scr.Vx + t->g.frame.x +
						 t->g.frame.width / 2) /
						Scr.MyDisplayWidth);
					strcat(tname, loc);
				}
				if (flags & SHOW_PAGE_Y)
				{
					sprintf(loc, "+%d",
						(Scr.Vy + t->g.frame.y +
						 t->g.frame.height/2) /
						Scr.MyDisplayHeight);
					strcat(tname, loc);
				}
				if (!(flags & NO_LAYER))
				{
					sprintf(loc, "(%d)",
						(get_layer(t)));
					strcat(tname, loc);
				}
				strcat(tname, ":");
				get_window_borders(t, &b);
				dheight = t->g.frame.height -
					b.total_size.height;
				dwidth = t->g.frame.width -
					b.total_size.width;

				dwidth = (dwidth - t->hints.base_width)
					  /t->orig_hints.width_inc;
				dheight = (dheight - t->hints.base_height)
					  /t->orig_hints.height_inc;

				sprintf(loc,"%d",dwidth);
				strcat(tname, loc);
				sprintf(loc,"x%d",dheight);
				strcat(tname, loc);
				if (t->g.frame.x >=0)
				{
					sprintf(loc,"+%d",t->g.frame.x);
				}
				else
				{
					sprintf(loc,"%d",t->g.frame.x);
				}
				strcat(tname, loc);
				if (t->g.frame.y >=0)
				{
					sprintf(loc,"+%d",t->g.frame.y);
				}
				else
				{
					sprintf(loc,"%d",t->g.frame.y);
				}
				strcat(tname, loc);

				if (IS_STICKY_ACROSS_PAGES(t) ||
				    IS_STICKY_ACROSS_DESKS(t))
				{
					strcat(tname, " S");
				}
				if (IS_ICONIFIED(t))
				{
					strcat(tname, ")");
				}
				strcat(t_hot,"\t");
				strcat(t_hot,tname);
			}
			ffunc = func ? func : "WindowListFunc";
			tfunc = safemalloc(strlen(ffunc) + 36);
			/* support two ways for now: window context
			 * (new) and window id param (old) */
			sprintf(tfunc, "WindowId %lu %s %lu",
				FW_W(t), ffunc, FW_W(t));
			AddToMenu(
				mr, t_hot, tfunc, False, False, False);
			free(tfunc);
			/* Add the title pixmap */
			if (FMiniIconsSupported && t->mini_icon)
			{
				MI_MINI_ICON(MR_LAST_ITEM(mr))[0] =
					t->mini_icon;
				/* increase the cache count. Otherwise the
				 * pixmap will be eventually removed from the
				 * cache by DestroyMenu */
				t->mini_icon->count++;
			}
			if (t_hot)
			{
				free(t_hot);
			}
			if (free_name)
			{
				free(name);
			}
		}
	}

	if (empty_menu)
	{
		/* force current desk title */
		tlabel = get_desk_title(desk, flags, True);
		AddToMenu(mr, tlabel, "TITLE", False, False, False);
		free(tlabel);
	}

	if (func)
	{
		free(func);
	}
	free(windowList);
	if (iconified_at_end)
	{
		free(iconifiedList);
	}
	/* Use the WindowList menu style if there is one */
	change_mr_menu_style(mr, "WindowList");

	/* Activate select_on_release style */
	old_sor_keycode = MST_SELECT_ON_RELEASE_KEY(mr);
	if (sor_keyname &&
	    (!MST_SELECT_ON_RELEASE_KEY(mr) ||
	     sor_keyname != sor_default_keyname))
	{
		MST_SELECT_ON_RELEASE_KEY(mr) =
			XKeysymToKeycode(
				dpy, FvwmStringToKeysym(dpy, sor_keyname));
	}

	memset(&mp, 0, sizeof(mp));
	mp.menu = mr;
	exc2 = exc_clone_context(exc, NULL, 0);
	mp.pexc = &exc2;
	mp.flags.has_default_action = (default_action && *default_action != 0);
	mp.flags.is_sticky = 1;
	mp.flags.is_submenu = 0;
	mp.flags.is_already_mapped = 0;
	mp.flags.is_triggered_by_keypress =
		(!default_action && exc->x.etrigger->type == KeyPress);
	mp.pops = &mops;
	mp.ret_paction = &ret_action;
	do_menu(&mp, &mret);
	/* Restore old menu style */
	MST_SELECT_ON_RELEASE_KEY(mr) = old_sor_keycode;
	if (ret_action)
	{
		free(ret_action);
	}
	DestroyMenu(mr, False, False);
	if (mret.rc == MENU_DOUBLE_CLICKED &&
	    default_action && *default_action)
	{
		execute_function(cond_rc, exc2, default_action, 0);
	}
	if (default_action != NULL)
	{
		free(default_action);
	}
	if (use_condition)
	{
		FreeConditionMask(&mask);
	}
	if (sor_keyname && sor_keyname != sor_default_keyname)
	{
		free(sor_keyname);
	}
	exc_destroy_context(exc2);

	return;
}
Example #14
0
File: focus.c Project: fvwmorg/fvwm
/*
 *
 * Moves focus to specified window; only to be called bay Focus and FlipFocus
 *
 */
static void __activate_window_by_command(
	F_CMD_ARGS, int is_focus_by_flip_focus_cmd)
{
	int cx;
	int cy;
	Bool do_not_warp;
	sftfwin_args_t sf_args;
	FvwmWindow * const fw = exc->w.fw;

	memset(&sf_args, 0, sizeof(sf_args));
	sf_args.do_allow_force_broadcast = 1;
	sf_args.is_focus_by_flip_focus_cmd = is_focus_by_flip_focus_cmd;
	sf_args.set_by = FOCUS_SET_BY_FUNCTION;
        sf_args.client_entered = 0;
	if (fw == NULL || !FP_DO_FOCUS_BY_FUNCTION(FW_FOCUS_POLICY(fw)))
	{
		UngrabEm(GRAB_NORMAL);
		if (fw)
		{
			/* give the window a chance to take the focus itself */
			sf_args.do_forbid_warp = 1;
			sf_args.do_force = 0;
			set_focus_to_fwin(FW_W(fw), fw, &sf_args);
		}
		return;
	}

	do_not_warp = StrEquals(PeekToken(action, NULL), "NoWarp");
	if (!do_not_warp)
	{
		if (fw->Desk != Scr.CurrentDesk)
		{
			goto_desk(fw->Desk);
		}
		if (IS_ICONIFIED(fw))
		{
			rectangle g;
			Bool rc;

			rc = get_visible_icon_title_geometry(fw, &g);
			if (rc == False)
			{
				get_visible_icon_picture_geometry(fw, &g);
			}
			cx = g.x + g.width / 2;
			cy = g.y + g.height / 2;
		}
		else
		{
			cx = fw->g.frame.x + fw->g.frame.width/2;
			cy = fw->g.frame.y + fw->g.frame.height/2;
		}
		if (
			cx < 0 || cx >= Scr.MyDisplayWidth ||
			cy < 0 || cy >= Scr.MyDisplayHeight)
		{
			int dx;
			int dy;

			dx = ((cx + Scr.Vx) / Scr.MyDisplayWidth) *
				Scr.MyDisplayWidth;
			dy = ((cy + Scr.Vy) / Scr.MyDisplayHeight) *
				Scr.MyDisplayHeight;
			MoveViewport(dx, dy, True);
		}
#if 0 /* can not happen */
		/* If the window is still not visible, make it visible! */
		if (fw->g.frame.x + fw->g.frame.width < 0 ||
		    fw->g.frame.y + fw->g.frame.height < 0 ||
		    fw->g.frame.x >= Scr.MyDisplayWidth ||
		    fw->g.frame.y >= Scr.MyDisplayHeight)
		{
			frame_setup_window(
				fw, 0, 0, fw->g.frame.width,
				fw->g.frame.height, False);
			if (
				FP_DO_WARP_POINTER_ON_FOCUS_FUNC(
					FW_FOCUS_POLICY(fw)))
			{
				FWarpPointerUpdateEvpos(
					exc->x.elast, dpy, None, Scr.Root, 0,
					0, 0, 0, 2, 2);
			}
		}
#endif
	}
	UngrabEm(GRAB_NORMAL);

	if (fw->Desk == Scr.CurrentDesk)
	{
		FvwmWindow *sf;

		sf = get_focus_window();
		sf_args.do_forbid_warp = !!do_not_warp;
		sf_args.do_force = 0;
                sf_args.client_entered = 0;
		set_focus_to_fwin(FW_W(fw), fw, &sf_args);
		if (sf != get_focus_window())
		{
			/* Ignore EnterNotify event while we are waiting for
			 * this window to be focused. */
			Scr.focus_in_pending_window = sf;
		}
	}

	return;
}