2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
23 #include "libs/fvwmlib.h"
24 #include "libs/ColorUtils.h"
25 #include "libs/Cursor.h"
26 #include "libs/Parse.h"
27 #include "libs/Strings.h"
29 #include "libs/PictureImageLoader.h"
32 #include "functions.h"
39 /* ---------------------------- local definitions -------------------------- */
41 /* ---------------------------- local macros ------------------------------- */
43 /* ---------------------------- imports ------------------------------------ */
45 /* ---------------------------- included code files ------------------------ */
47 /* ---------------------------- local types -------------------------------- */
49 /* ---------------------------- forward declarations ----------------------- */
51 /* ---------------------------- local variables ---------------------------- */
53 static Cursor cursors
[CRS_MAX
];
54 static const unsigned int default_cursors
[CRS_MAX
] =
57 XC_top_left_corner
, /* CRS_POSITION */
58 XC_top_left_arrow
, /* CRS_TITLE */
59 XC_top_left_arrow
, /* CRS_DEFAULT */
60 XC_hand2
, /* CRS_SYS */
61 XC_fleur
, /* CRS_MOVE */
62 XC_sizing
, /* CRS_RESIZE */
63 XC_watch
, /* CRS_WAIT */
64 XC_top_left_arrow
, /* CRS_MENU */
65 XC_crosshair
, /* CRS_SELECT */
66 XC_pirate
, /* CRS_DESTROY */
67 XC_top_side
, /* CRS_TOP */
68 XC_right_side
, /* CRS_RIGHT */
69 XC_bottom_side
, /* CRS_BOTTOM */
70 XC_left_side
, /* CRS_LEFT */
71 XC_top_left_corner
, /* CRS_TOP_LEFT */
72 XC_top_right_corner
, /* CRS_TOP_RIGHT */
73 XC_bottom_left_corner
, /* CRS_BOTTOM_LEFT */
74 XC_bottom_right_corner
, /* CRS_BOTTOM_RIGHT */
75 XC_top_side
, /* CRS_TOP_EDGE */
76 XC_right_side
, /* CRS_RIGHT_EDGE */
77 XC_bottom_side
, /* CRS_BOTTOM_EDGE */
78 XC_left_side
, /* CRS_LEFT_EDGE */
79 XC_left_ptr
, /* CRS_ROOT */
80 XC_plus
/* CRS_STROKE */
83 /* ---------------------------- exported variables (globals) --------------- */
85 /* ---------------------------- local functions ---------------------------- */
87 static void SafeDefineCursor(Window w
, Cursor cursor
)
91 XDefineCursor(dpy
,w
,cursor
);
97 /* ---------------------------- interface functions ------------------------ */
99 /* CreateCursors - Loads fvwm cursors */
100 Cursor
*CreateCursors(Display
*dpy
)
105 for (i
= 1; i
< CRS_MAX
; i
++)
107 cursors
[i
] = XCreateFontCursor(dpy
, default_cursors
[i
]);
113 /* ---------------------------- builtin commands --------------------------- */
115 void CMD_CursorStyle(F_CMD_ARGS
)
118 char *newcursor
=NULL
;
131 cname
= PeekToken(action
, &action
);
134 fvwm_msg(ERR
, "CursorStyle", "Bad cursor style");
138 if (StrEquals("POSITION", cname
))
140 index
= CRS_POSITION
;
142 else if (StrEquals("DEFAULT", cname
))
146 else if (StrEquals("SYS", cname
))
150 else if (StrEquals("TITLE", cname
))
154 else if (StrEquals("MOVE", cname
))
158 else if (StrEquals("RESIZE", cname
))
162 else if (StrEquals("MENU", cname
))
166 else if (StrEquals("WAIT", cname
))
170 else if (StrEquals("SELECT", cname
))
174 else if (StrEquals("DESTROY", cname
))
178 else if (StrEquals("LEFT", cname
))
182 else if (StrEquals("RIGHT", cname
))
186 else if (StrEquals("TOP", cname
))
190 else if (StrEquals("BOTTOM", cname
))
194 else if (StrEquals("TOP_LEFT", cname
))
196 index
= CRS_TOP_LEFT
;
198 else if (StrEquals("TOP_RIGHT", cname
))
200 index
= CRS_TOP_RIGHT
;
202 else if (StrEquals("BOTTOM_LEFT", cname
))
204 index
= CRS_BOTTOM_LEFT
;
206 else if (StrEquals("BOTTOM_RIGHT", cname
))
208 index
= CRS_BOTTOM_RIGHT
;
210 else if (StrEquals("LEFT_EDGE", cname
))
212 index
= CRS_LEFT_EDGE
;
214 else if (StrEquals("RIGHT_EDGE", cname
))
216 index
= CRS_RIGHT_EDGE
;
218 else if (StrEquals("TOP_EDGE", cname
))
220 index
= CRS_TOP_EDGE
;
222 else if (StrEquals("BOTTOM_EDGE", cname
))
224 index
= CRS_BOTTOM_EDGE
;
226 else if (StrEquals("ROOT", cname
))
230 else if (StrEquals("STROKE", cname
))
236 fvwm_msg(ERR
, "CursorStyle", "Unknown cursor name %s", cname
);
242 /* check if the cursor is given by X11 name */
243 action
= GetNextToken(action
, &newcursor
);
246 my_nc
= fvwmCursorNameToIndex(newcursor
);
250 my_nc
= default_cursors
[index
];
255 nc
= strtol(newcursor
, &errpos
, 10);
256 if (errpos
&& *errpos
== '\0')
268 /* newcursor was a number or the name of a X11 cursor */
269 if ((nc
< 0) || (nc
>= XC_num_glyphs
) || ((nc
% 2) != 0))
272 ERR
, "CursorStyle", "Bad cursor number %s",
278 cursor
= XCreateFontCursor(dpy
, nc
);
282 /* newcursor was not a number neither a X11 cursor name */
284 StrEquals("none", newcursor
) ||
285 StrEquals("tiny", newcursor
))
291 (tolower(*newcursor
) == 'n') ? 0 : 1);
293 dpy
, Scr
.ScratchMonoPixmap
, Scr
.MonoGC
,
295 cursor
= XCreatePixmapCursor(
296 dpy
, Scr
.ScratchMonoPixmap
,
297 Scr
.ScratchMonoPixmap
, &nccol
, &nccol
, 0, 0);
307 path
= PictureFindImageFile(newcursor
, NULL
, R_OK
);
312 "Cursor %s not found", newcursor
);
317 if (GetIntegerArguments(action
, &tmp
, hotspot
, 2) == 2)
321 cursor
= PImageLoadCursorFromFile(
322 dpy
, Scr
.Root
, path
, hotspot
[0], hotspot
[1]);
329 ERR
, "CursorStyle", "Cannot load cursor: %s",
338 /* replace the cursor defn */
339 if (Scr
.FvwmCursors
[index
])
341 XFreeCursor(dpy
, Scr
.FvwmCursors
[index
]);
343 Scr
.FvwmCursors
[index
] = cursor
;
345 /* look for optional color arguments */
346 action
= GetNextToken(action
, &fore
);
347 action
= GetNextToken(action
, &back
);
350 colors
[0].pixel
= GetColor(fore
);
351 colors
[1].pixel
= GetColor(back
);
352 XQueryColors (dpy
, Pcmap
, colors
, 2);
354 dpy
, Scr
.FvwmCursors
[index
], &(colors
[0]),
366 /* redefine all the windows using cursors */
367 for (fw2
= Scr
.FvwmRoot
.next
; fw2
; fw2
= fw2
->next
)
369 if (!HAS_HANDLES(fw2
))
371 /* Ignore windows without handles */
374 for (i
= 0; i
< 4; i
++)
378 Scr
.FvwmCursors
[CRS_TOP_LEFT
+ i
]);
381 Scr
.FvwmCursors
[CRS_TOP
+ i
]);
383 for (i
= 0; i
/ 2 < Scr
.nr_left_buttons
; i
+= 2)
386 FW_W_BUTTON(fw2
, i
), Scr
.FvwmCursors
[CRS_SYS
]);
388 for (i
= 1; i
/ 2 < Scr
.nr_right_buttons
; i
+= 2)
391 FW_W_BUTTON(fw2
, i
), Scr
.FvwmCursors
[CRS_SYS
]);
393 SafeDefineCursor(FW_W_TITLE(fw2
), Scr
.FvwmCursors
[CRS_TITLE
]);
394 if (index
== CRS_DEFAULT
)
397 FW_W_FRAME(fw2
), Scr
.FvwmCursors
[CRS_DEFAULT
]);
399 FW_W_PARENT(fw2
), Scr
.FvwmCursors
[CRS_DEFAULT
]);
400 if (IS_ICONIFIED(fw2
))
402 if (!HAS_NO_ICON_TITLE(fw2
))
405 FW_W_ICON_TITLE(fw2
),
406 Scr
.FvwmCursors
[CRS_DEFAULT
]);
408 if (FW_W_ICON_PIXMAP(fw2
) != None
)
411 FW_W_ICON_PIXMAP(fw2
),
412 Scr
.FvwmCursors
[CRS_DEFAULT
]);
418 /* Do the menus for good measure */
419 SetMenuCursor(Scr
.FvwmCursors
[CRS_MENU
]);
421 SafeDefineCursor(Scr
.PanFrameTop
.win
, Scr
.FvwmCursors
[CRS_TOP_EDGE
]);
423 Scr
.PanFrameBottom
.win
, Scr
.FvwmCursors
[CRS_BOTTOM_EDGE
]);
424 SafeDefineCursor(Scr
.PanFrameLeft
.win
, Scr
.FvwmCursors
[CRS_LEFT_EDGE
]);
426 Scr
.PanFrameRight
.win
, Scr
.FvwmCursors
[CRS_RIGHT_EDGE
]);
427 /* migo (04/Nov/1999): don't annoy users which use xsetroot */
428 if (index
== CRS_ROOT
)
430 SafeDefineCursor(Scr
.Root
, Scr
.FvwmCursors
[CRS_ROOT
]);
436 /* Defines in which cases fvwm "grab" the cursor during execution of certain
438 void CMD_BusyCursor(F_CMD_ARGS
)
441 char *optstring
= NULL
;
445 "read", "wait", "modulesynchronous", "dynamicmenu", "*", NULL
448 while (action
&& *action
!= '\0')
450 action
= GetQuotedString(
451 action
, &optstring
, ",", NULL
, NULL
, NULL
);
457 args
= GetNextToken(optstring
, &option
);
464 flag
= ParseToggleArgument(args
, NULL
, -1, True
);
468 fvwm_msg(ERR
, "BusyCursor",
469 "error in boolean specification");
474 switch (GetTokenIndex(option
, optlist
, 0, NULL
))
479 Scr
.BusyCursor
|= BUSY_READ
;
483 Scr
.BusyCursor
&= ~BUSY_READ
;
490 Scr
.BusyCursor
|= BUSY_WAIT
;
494 Scr
.BusyCursor
&= ~BUSY_WAIT
;
498 case 2: /* modulesynchronous */
501 Scr
.BusyCursor
|= BUSY_MODULESYNCHRONOUS
;
505 Scr
.BusyCursor
&= ~BUSY_MODULESYNCHRONOUS
;
509 case 3: /* dynamicmenu */
512 Scr
.BusyCursor
|= BUSY_DYNAMICMENU
;
516 Scr
.BusyCursor
&= ~BUSY_DYNAMICMENU
;
523 Scr
.BusyCursor
|= BUSY_ALL
;
527 Scr
.BusyCursor
&= ~(BUSY_ALL
);
532 fvwm_msg(ERR
, "BusyCursor", "unknown context '%s'",