/* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdio.h>
#include "libs/fvwmlib.h"
#include "fvwm.h"
#include "externs.h"
#include "cursor.h"
#include "functions.h"
#include "bindings.h"
#include "misc.h"
#include "screen.h"
#include "cursor.h"
#include "menus.h"
static Cursor cursors[CRS_MAX];
static const unsigned int default_cursors[CRS_MAX] =
{
None,
XC_top_left_corner, /* CRS_POSITION */
XC_top_left_arrow, /* CRS_TITLE */
XC_top_left_arrow, /* CRS_DEFAULT */
XC_hand2, /* CRS_SYS */
XC_fleur, /* CRS_MOVE */
XC_sizing, /* CRS_RESIZE */
XC_watch, /* CRS_WAIT */
XC_top_left_arrow, /* CRS_MENU */
XC_crosshair, /* CRS_SELECT */
XC_pirate, /* CRS_DESTROY */
XC_top_side, /* CRS_TOP */
XC_right_side, /* CRS_RIGHT */
XC_bottom_side, /* CRS_BOTTOM */
XC_left_side, /* CRS_LEFT */
XC_top_left_corner, /* CRS_TOP_LEFT */
XC_top_right_corner, /* CRS_TOP_RIGHT */
XC_bottom_left_corner, /* CRS_BOTTOM_LEFT */
XC_bottom_right_corner, /* CRS_BOTTOM_RIGHT */
XC_top_side, /* CRS_TOP_EDGE */
XC_right_side, /* CRS_RIGHT_EDGE */
XC_bottom_side, /* CRS_BOTTOM_EDGE */
XC_left_side, /* CRS_LEFT_EDGE */
XC_left_ptr, /* CRS_ROOT */
XC_plus /* CRS_STROKE */
};
/***********************************************************************
*
* Procedure:
* CreateCursors - Loads fvwm cursors
*
***********************************************************************/
Cursor *CreateCursors(Display *dpy)
{
int i;
/* define cursors */
cursors[0] = None;
for (i = 1; i < CRS_MAX; i++)
{
cursors[i] = XCreateFontCursor(dpy, default_cursors[i]);
}
return cursors;
}
static void SafeDefineCursor(Window w, Cursor cursor)
{
if (w)
XDefineCursor(dpy,w,cursor);
}
void CMD_CursorStyle(F_CMD_ARGS)
{
char *cname=NULL, *newcursor=NULL;
char *errpos = NULL;
#ifdef XPM
char *path = NULL;
#endif
char *fore = NULL, *back = NULL;
XColor colors[2];
int index,nc,i,my_nc;
FvwmWindow *fw;
action = GetNextToken(action,&cname);
action = GetNextToken(action,&newcursor);
if (!cname)
{
fvwm_msg(ERR,"CursorStyle","Bad cursor style");
if (cname)
free(cname);
return;
}
if (StrEquals("POSITION",cname)) index = CRS_POSITION;
else if (StrEquals("DEFAULT",cname)) index = CRS_DEFAULT;
else if (StrEquals("SYS",cname)) index = CRS_SYS;
else if (StrEquals("TITLE",cname)) index = CRS_TITLE;
else if (StrEquals("MOVE",cname)) index = CRS_MOVE;
else if (StrEquals("RESIZE",cname)) index = CRS_RESIZE;
else if (StrEquals("MENU",cname)) index = CRS_MENU;
else if (StrEquals("WAIT",cname)) index = CRS_WAIT;
else if (StrEquals("SELECT",cname)) index = CRS_SELECT;
else if (StrEquals("DESTROY",cname)) index = CRS_DESTROY;
else if (StrEquals("LEFT",cname)) index = CRS_LEFT;
else if (StrEquals("RIGHT",cname)) index = CRS_RIGHT;
else if (StrEquals("TOP",cname)) index = CRS_TOP;
else if (StrEquals("BOTTOM",cname)) index = CRS_BOTTOM;
else if (StrEquals("TOP_LEFT",cname)) index = CRS_TOP_LEFT;
else if (StrEquals("TOP_RIGHT",cname)) index = CRS_TOP_RIGHT;
else if (StrEquals("BOTTOM_LEFT",cname)) index = CRS_BOTTOM_LEFT;
else if (StrEquals("BOTTOM_RIGHT",cname)) index = CRS_BOTTOM_RIGHT;
else if (StrEquals("LEFT_EDGE",cname)) index = CRS_LEFT_EDGE;
else if (StrEquals("RIGHT_EDGE",cname)) index = CRS_RIGHT_EDGE;
else if (StrEquals("TOP_EDGE",cname)) index = CRS_TOP_EDGE;
else if (StrEquals("BOTTOM_EDGE",cname)) index = CRS_BOTTOM_EDGE;
else if (StrEquals("ROOT",cname)) index = CRS_ROOT;
else if (StrEquals("STROKE",cname)) index = CRS_STROKE;
else
{
fvwm_msg(ERR,"CursorStyle","Unknown cursor name %s",cname);
free(cname);
free(newcursor);
return;
}
free(cname);
/* check if the cursor is given by X11 name */
if (newcursor)
my_nc = fvwmCursorNameToIndex(newcursor);
else
my_nc = default_cursors[index];
if (my_nc == -1)
{
nc = strtol(newcursor, &errpos, 10);
if (errpos && *errpos == '\0')
my_nc = 0;
}
else
nc = my_nc;
if (my_nc > -1)
{
/* newcursor was a number or the name of a X11 cursor */
if ((nc < 0) || (nc >= XC_num_glyphs) || ((nc % 2) != 0))
{
fvwm_msg(ERR, "CursorStyle", "Bad cursor number %s", newcursor);
free(newcursor);
return;
}
free(newcursor);
/* replace the cursor defn */
if (Scr.FvwmCursors[index])
XFreeCursor(dpy,Scr.FvwmCursors[index]);
Scr.FvwmCursors[index] = XCreateFontCursor(dpy,nc);
}
else
{
/* newcursor was not a number neither a X11 cursor name */
if (StrEquals("none", newcursor) || StrEquals("tiny", newcursor))
{
static Pixmap nocursor = None;
XColor nccol;
if (nocursor == None)
{
if (Scr.FvwmCursors[index])
XFreeCursor (dpy, Scr.FvwmCursors[index]);
XSetForeground(dpy, Scr.MonoGC, (tolower(*newcursor) == 'n') ? 0 : 1);
XFillRectangle(dpy, Scr.ScratchMonoPixmap, Scr.MonoGC, 0, 0, 1, 1);
Scr.FvwmCursors[index] =
XCreatePixmapCursor(
dpy, Scr.ScratchMonoPixmap, Scr.ScratchMonoPixmap, &nccol, &nccol,
0, 0);
free (newcursor);
}
}
else
{
#ifdef XPM
XpmAttributes xpm_attributes;
Pixmap source, mask;
unsigned int x;
unsigned int y;
path = findImageFile (newcursor, NULL, R_OK);
if (!path)
{
fvwm_msg (ERR, "CursorStyle", "Cursor %s not found", newcursor);
free (newcursor);
return;
}
xpm_attributes.depth = 1; /* we need source to be a bitmap */
xpm_attributes.valuemask = XpmSize | XpmDepth | XpmHotspot;
if (XpmReadFileToPixmap (dpy, Scr.Root, path, &source, &mask,
&xpm_attributes) != XpmSuccess)
{
fvwm_msg (ERR, "CursorStyle", "Error reading cursor xpm %s",
newcursor);
free (newcursor);
return;
}
colors[0].pixel = GetColor(DEFAULT_CURSOR_FORE_COLOR);
colors[1].pixel = GetColor(DEFAULT_CURSOR_BACK_COLOR);
XQueryColors (dpy, Pcmap, colors, 2);
if (Scr.FvwmCursors[index])
XFreeCursor (dpy, Scr.FvwmCursors[index]);
x = xpm_attributes.x_hotspot;
if (x >= xpm_attributes.width)
x = xpm_attributes.width / 2;
y = xpm_attributes.y_hotspot;
if (y >= xpm_attributes.height)
y = xpm_attributes.height / 2;
Scr.FvwmCursors[index] =
XCreatePixmapCursor(
dpy, source, mask, &(colors[0]), &(colors[1]), x, y);
free (newcursor);
free (path);
#else /* ! XPM */
fvwm_msg(ERR, "CursorStyle", "Bad cursor name or number %s", newcursor);
free (newcursor);
return;
#endif
}
}
/* look for optional color arguments */
action = GetNextToken(action, &fore);
action = GetNextToken(action, &back);
if (fore && back)
{
colors[0].pixel = GetColor(fore);
colors[1].pixel = GetColor(back);
XQueryColors (dpy, Pcmap, colors, 2);
XRecolorCursor (dpy, Scr.FvwmCursors[index], &(colors[0]), &(colors[1]));
}
if (fore)
free(fore);
if (back)
free(back);
/* redefine all the windows using cursors */
fw = Scr.FvwmRoot.next;
while(fw)
{
for (i=0;i<4;i++)
{
SafeDefineCursor(fw->corners[i],Scr.FvwmCursors[CRS_TOP_LEFT+i]);
SafeDefineCursor(fw->sides[i],Scr.FvwmCursors[CRS_TOP+i]);
}
for (i = 0 ; i / 2 < Scr.nr_left_buttons; i += 2)
{
SafeDefineCursor(fw->button_w[i],Scr.FvwmCursors[CRS_SYS]);
}
for (i = 1 ; i / 2 < Scr.nr_right_buttons; i += 2)
{
SafeDefineCursor(fw->button_w[i],
Scr.FvwmCursors[CRS_SYS]);
}
SafeDefineCursor(fw->title_w, Scr.FvwmCursors[CRS_TITLE]);
if (index == CRS_DEFAULT)
{
SafeDefineCursor(fw->frame, Scr.FvwmCursors[CRS_DEFAULT]);
SafeDefineCursor(fw->Parent, Scr.FvwmCursors[CRS_DEFAULT]);
SafeDefineCursor(fw->decor_w, Scr.FvwmCursors[CRS_DEFAULT]);
if (IS_ICONIFIED(fw))
{
if (!HAS_NO_ICON_TITLE(fw))
SafeDefineCursor(fw->icon_w, Scr.FvwmCursors[CRS_DEFAULT]);
if (fw->icon_pixmap_w != None)
SafeDefineCursor(fw->icon_pixmap_w, Scr.FvwmCursors[CRS_DEFAULT]);
}
}
fw = fw->next;
}
/* Do the menus for good measure */
SetMenuCursor(Scr.FvwmCursors[CRS_MENU]);
SafeDefineCursor(Scr.PanFrameTop.win, Scr.FvwmCursors[CRS_TOP_EDGE]);
SafeDefineCursor(Scr.PanFrameBottom.win, Scr.FvwmCursors[CRS_BOTTOM_EDGE]);
SafeDefineCursor(Scr.PanFrameLeft.win, Scr.FvwmCursors[CRS_LEFT_EDGE]);
SafeDefineCursor(Scr.PanFrameRight.win, Scr.FvwmCursors[CRS_RIGHT_EDGE]);
/* migo (04/Nov/1999): don't annoy users which use xsetroot */
if (index == CRS_ROOT)
SafeDefineCursor(Scr.Root, Scr.FvwmCursors[CRS_ROOT]);
}
/***********************************************************************
*
* builtin function: (set)BusyCursor
* Defines in which cases fvwm "grab" the cursor during execution of
* certain functions.
*
***********************************************************************/
void CMD_BusyCursor(F_CMD_ARGS)
{
char *option = NULL;
char *optstring = NULL;
char *args = NULL;
int flag = -1;
char *optlist[] = {
"read", "wait", "modulesynchronous", "dynamicmenu", "*", NULL
};
while (action && *action != '\0')
{
action = GetQuotedString(action, &optstring, ",", NULL, NULL, NULL);
if (!optstring)
break;
args = GetNextToken(optstring, &option);
if (!option)
{
free(optstring);
break;
}
flag = ParseToggleArgument(args, NULL, -1, True);
free(optstring);
if (flag == -1)
{
fvwm_msg(ERR, "BusyCursor", "error in boolean specification");
free(option);
break;
}
switch (GetTokenIndex(option, optlist, 0, NULL))
{
case 0: /* read */
if (flag)
Scr.BusyCursor |= BUSY_READ;
else
Scr.BusyCursor &= ~BUSY_READ;
break;
case 1: /* wait */
if (flag)
Scr.BusyCursor |= BUSY_WAIT;
else
Scr.BusyCursor &= ~BUSY_WAIT;
break;
case 2: /* modulesynchronous */
if (flag)
Scr.BusyCursor |= BUSY_MODULESYNCHRONOUS;
else
Scr.BusyCursor &= ~BUSY_MODULESYNCHRONOUS;
break;
case 3: /* dynamicmenu */
if (flag)
Scr.BusyCursor |= BUSY_DYNAMICMENU;
else
Scr.BusyCursor &= ~BUSY_DYNAMICMENU;
break;
case 4: /* "*" */
if (flag)
Scr.BusyCursor |= BUSY_ALL;
else
Scr.BusyCursor &= ~(BUSY_ALL);
break;
default:
fvwm_msg(ERR, "BusyCursor", "unknown context '%s'", option);
break;
}
free(option);
}
}
syntax highlighted by Code2HTML, v. 0.9.1