[comp.windows.x.motif] cursor fonts

horst@aida.pcs.com (horst kern) (11/20/90)

There was a recent posting asking how to change the cursor font to the 
watch cursor. 

The three replies were unsatisfactory in my opinion, as two of them
showed how to change the cursor font to the watch cursor. (Nonetheless 
many thanks to them.) 

Of course the problem implies the question "how to change it back to
the original font when the work is done". The third answer addressed
this question but used a procedure call "set_cursor" that does not
exist in the (our?) Motif environment. 

Of course it would be nice to have some way to ask Motif or X for the
current value of the cursor. Finding nothing like that, I wrote a
small program to be at least able to display all possible cursor
fonts by selecting their name from a list.

Have fun,
 Horst

==========
Horst Kern                                     PCS Computer Systeme GmbH
Tel.       :      089/68004-279                Pfaelzer-Wald-Str. 36
DOMAIN     :      horst@aida.pcs.com           D 8000 Muenchen 90
UUCP-Europe:      ...unido!pcsbst!horst
UUCP-USA   :      ...pyramid!pcsbst!hk

--------------------------------- 8< -----------------------------
#! /bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of shell archive."
# Contents:  cursor.c makefile
# Wrapped by horst@aida on Tue Nov 20 10:32:31 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'cursor.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'cursor.c'\"
else
echo shar: Extracting \"'cursor.c'\" \(4482 characters\)
sed "s/^X//" >'cursor.c' <<'END_OF_FILE'
X#include <X11/Intrinsic.h>
X#include <X11/cursorfont.h>
X#include <Mrm/MrmAppl.h>                   /* Motif Toolkit */
X#include <Xm/Xm.h>
X#include <Xm/CascadeB.h>
X#include <Xm/MainW.h>
X#include <Xm/List.h>
X#include <Xm/PushB.h>
X#include <Xm/RowColumn.h>
X
XXtAppContext context;
Display *display;
Widget applShell;
X
void init_widgets();
void quit();
void sel();
X
static XtCallbackRec sel_cbs[] = {
X	{sel, (caddr_t)NULL},
X	{ (XtCallbackProc)NULL, (caddr_t)NULL },
X};
X
X/* Check consistency of this list with your file "<X11/cursorfont.h>"
X*  The values of these #defines should be even numbers without holes.
X*/
X#define CURSORNUM 77
static char *table[]={
X"XC_X_cursor",
X"XC_arrow",
X"XC_based_arrow_down",
X"XC_based_arrow_up",
X"XC_boat",
X"XC_bogosity",
X"XC_bottom_left_corner",
X"XC_bottom_right_corner",
X"XC_bottom_side",
X"XC_bottom_tee",
X"XC_box_spiral",
X"XC_center_ptr",
X"XC_circle",
X"XC_clock",
X"XC_coffee_mug",
X"XC_cross",
X"XC_cross_reverse",
X"XC_crosshair",
X"XC_diamond_cross",
X"XC_dot",
X"XC_dotbox",
X"XC_double_arrow",
X"XC_draft_large",
X"XC_draft_small",
X"XC_draped_box",
X"XC_exchange",
X"XC_fleur",
X"XC_gobbler",
X"XC_gumby",
X"XC_hand1",
X"XC_hand2",
X"XC_heart",
X"XC_icon",
X"XC_iron_cross",
X"XC_left_ptr",
X"XC_left_side",
X"XC_left_tee",
X"XC_leftbutton",
X"XC_ll_angle",
X"XC_lr_angle",
X"XC_man",
X"XC_middlebutton",
X"XC_mouse",
X"XC_pencil",
X"XC_pirate",
X"XC_plus",
X"XC_question_arrow",
X"XC_right_ptr",
X"XC_right_side",
X"XC_right_tee",
X"XC_rightbutton",
X"XC_rtl_logo",
X"XC_sailboat",
X"XC_sb_down_arrow",
X"XC_sb_h_double_arrow",
X"XC_sb_left_arrow",
X"XC_sb_right_arrow",
X"XC_sb_up_arrow",
X"XC_sb_v_double_arrow",
X"XC_shuttle",
X"XC_sizing",
X"XC_spider",
X"XC_spraycan",
X"XC_star",
X"XC_target",
X"XC_tcross",
X"XC_top_left_arrow",
X"XC_top_left_corner",
X"XC_top_right_corner",
X"XC_top_side",
X"XC_top_tee",
X"XC_trek",
X"XC_ul_angle",
X"XC_umbrella",
X"XC_ur_angle",
X"XC_watch",
X"XC_xterm",
X};
X
void main (argc,argv)
unsigned int	argc;
char 		**argv;
X{
X
X	/*	Initialize toolkit and open display.
X	*/
X	XtToolkitInitialize ();
X
X	context=XtCreateApplicationContext();
X
X	display = XtOpenDisplay (context, (String)NULL, (String)NULL,
X			"uebung",
X			(XrmOptionDescRec *)NULL, 0, &argc, argv);
X	if (!display)
X	{
X		XtWarning ("cursor: can't open display, exiting...");
X		exit (0);
X	}
X
X
X	/*	Create ApplicationShell.
X	*/
X	applShell = XtAppCreateShell ((String)NULL, "cursor",
X			applicationShellWidgetClass, display,
X			(ArgList)NULL, 0);
X
X
X	init_widgets();
X
X	/*	Realize toplevel widgets.
X	*/
X	XtRealizeWidget (applShell);
X
X
X	/*	Process events.
X	*/
X	XtAppMainLoop (context);
X}
X
X
void init_widgets ()
X{
X	Arg args[10];
X	Cardinal n;
X	Widget main_window;     /*  MainWindow          */
X	Widget scrolled_list;   /*  ScrolledWindow      */
X	Widget menu_pane;       /*  MenuPane            */
X	Widget menu_bar;
X	Widget cascade;
X	Widget button;
X	XmStringTable StrTab;
X	XmString tcs;
X	int j;
X
X	n = 0;
X	main_window = XmCreateMainWindow (applShell, "main1", args, n);
X	XtManageChild (main_window);
X
X	n = 0;
X	menu_bar = XmCreateMenuBar (main_window, "menu_bar", args, n); 
X	XtManageChild (menu_bar);
X
X	n = 0;
X	menu_pane = XmCreatePulldownMenu (menu_bar, "menu_pane", args, n);
X
X	n = 0;
X	button = XmCreatePushButton (menu_pane, "Quit", args, n);
X	XtManageChild (button);
X	XtAddCallback (button, XmNactivateCallback, quit, NULL);
X
X	n = 0;
X	XtSetArg (args[n], XmNsubMenuId, menu_pane);  n++;
X	cascade = XmCreateCascadeButton (menu_bar, "Exit", args, n);
X	XtManageChild (cascade);
X
X	StrTab = (XmStringTable) XtMalloc (CURSORNUM * sizeof(XmString));
X	for (j=0; j<CURSORNUM; j++) {
X	    tcs = XmStringLtoRCreate(table[j], XmSTRING_DEFAULT_CHARSET);
X	    StrTab [j] = tcs;
X	}
X
X	n = 0;
X	XtSetArg(args[n], XmNitems, (XtArgVal) StrTab);n++;
X	XtSetArg(args[n], XmNitemCount, (XtArgVal) CURSORNUM);n++;
X	XtSetArg(args[n], XmNvisibleItemCount, 30);n++;
X	XtSetArg(args[n], XmNselectionPolicy, XmSINGLE_SELECT);n++;
X	XtSetArg(args[n], XmNsingleSelectionCallback, sel_cbs);n++;
X
X	scrolled_list = XmCreateScrolledList (main_window, "list", args, n);
X	XtManageChild (scrolled_list);
X}
X
void quit (w, client_data, call_data)
Widget w;
caddr_t client_data, call_data;
X{
X	exit(0);
X}
X
void sel (w, client_data, call_data)
Widget w;
caddr_t client_data;
XXmListCallbackStruct *call_data;
X{
X	Cursor new_cursor;
X	int c_index = call_data -> item_position - 1;
X	/* They've numbered them with even numbers: */
X	new_cursor = XCreateFontCursor(XtDisplay(w), c_index * 2);
X	XDefineCursor(XtDisplay(w), XtWindow(w), new_cursor);
X	XFlush(XtDisplay(w));
X}
X
END_OF_FILE
if test 4482 -ne `wc -c <'cursor.c'`; then
    echo shar: \"'cursor.c'\" unpacked with wrong size!
fi
# end of 'cursor.c'
fi
if test -f 'makefile' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'makefile'\"
else
echo shar: Extracting \"'makefile'\" \(488 characters\)
sed "s/^X//" >'makefile' <<'END_OF_FILE'
NAME=cursor
CC=cc
DEFINES  = -DSYSV -DPCS
INCLUDES = -I/usr/include/Motif
LIBDIR   = -L/usr/lib/Motif -L/usr/lib/X11
MLIBS     = -lMrm -lXm -lXt -lX11 -lPW -lbsd    #PCS libs
X#MLIBS     = -lMrm -lXm -lXt -lX11 -lPW          #others
CFLAGS = -g
all: ${NAME} ${NAME}.uid
X${NAME}: ${NAME}.o
X	${CC} ${NAME}.o -o ${NAME} \
X	   ${LIBDIR} \
X	   ${MLIBS}
X
X${NAME}.o: ${NAME}.c
X	${CC} -g -c ${NAME}.c ${DEFINES} ${INCLUDES}
X${NAME}.uid: ${NAME}.uil
X	uil -o ${NAME}.uid ${NAME}.uil ${INCLUDES}/uil
END_OF_FILE
if test 488 -ne `wc -c <'makefile'`; then
    echo shar: \"'makefile'\" unpacked with wrong size!
fi
# end of 'makefile'
fi
echo shar: End of shell archive.
exit 0

argv@turnpike.Eng.Sun.COM (Dan Heller) (11/21/90)

In article <1003@pcsbst.pcs.com> horst@aida.pcs.com (horst kern) writes:
> There was a recent posting asking how to change the cursor font to the 
> watch cursor. 

Recent?

> Of course the problem implies the question "how to change it back to
> the original font when the work is done".

It's not just that, but you don't want to process input while the
cursor is that font.  further, you don't want anything that may
have happened (mouse buttons or keyboard events) while the cursor
was changed to sudedenly "take action" when you are done.

I've found that the easiest thing to do (so far) is to create a
single InputOnly window (you can use XCreateWindow() for this) that
goes over the entire screen (DefaultWidget() and DefaultHeight())
(don't forget to call XMapWindow()) and call XtGrabPointer() setting
the _cursor_ parameter accordingly.  When you're done, ungrab the
pointer, unmap the input-only window and you should be done.  You
never change your cursor using this method -- you just add a new
window that has the cursor you want.*

Note; you have to do some XtAppProcessEvent() calls to make sure
that your window is mapped, or nothing will happen :-(.

It would sure be nice if one could communciate with mwm to do this
for you.
--
dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.

horst@aida.pcs.com (horst kern) (11/27/90)

In article <3206@exodus.Eng.Sun.COM> argv@turnpike.Eng.Sun.COM (Dan Heller) writes:
>In article <1003@pcsbst.pcs.com> horst@aida.pcs.com (horst kern) writes:
>> There was a recent posting asking how to change the cursor font to the 
>> watch cursor. 
>
>Recent?

Okay, everything is relative. Recent was meant to be based on Bavarian 
time units. 

>I've found that the easiest thing to do (so far) is to create a
>single InputOnly window (you can use XCreateWindow() for this) that
>goes over the entire screen (DefaultWidget() and DefaultHeight())

The problem seems to grow instead of being solved. Some e-mail from
Mike Websters (my thanks to him) told me to map the InputOnly window
on top of the one that I want it. You think it should be the whole
screen. As you mention, it's an easy way - so far. It's of course not
the best way, as people might have windows to other machines which are 
not at all affected by the absence of one particular main loop. Even
on one machine they might want to continue with another xterm while
that machine is also busy with an application. 

So the question comes to: "How do I determine which windows are on the 
screen that are children of my main program." It can surely be solved, 
but is not so easy to do. 

I even heard of the possibility to have several main loops in one
application, using several application contexts. However I _do_ use
several application contexts and do not have the impression that a
busy window of one context leaves the window of the other context
ready to process input. 

The problem needs a solution. Leaving and entering a busy (sub-)window
several times in a focus-on-enter environment makes the mwm so
angry that it goes on strike until the busy application is killed.

Regards,
 Horst

==========
Horst Kern                                     PCS Computer Systeme GmbH
Tel.       :      089/68004-279                Pfaelzer-Wald-Str. 36
DOMAIN     :      horst@aida.pcs.com           D 8000 Muenchen 90
UUCP-Europe:      ...unido!pcsbst!horst
UUCP-USA   :      ...pyramid!pcsbst!hk
------------------------------------------------------------------------

horst@aida.pcs.com (horst kern) (11/27/90)

In article <1019@pcsbst.pcs.com> horst@aida.pcs.com (horst kern) writes:
>Mike Websters (my thanks to him) told me to map the InputOnly window
 ^^^^^^^^^^^^^

Sorry, his name is Mike Wexler.

horst

aw@KITCHEN.BELLCORE.COM (Andrew Wason, aw@cellar.bae.bellcore.com) (11/28/90)

eru!hagbard!sunic!mcsun!unido!pcsbst!aida!horst@bloom-beacon.mit.edu (horst ker
n) writes:
> 
> 
> In article <3206@exodus.Eng.Sun.COM> argv@turnpike.Eng.Sun.COM (Dan Heller) w
> rites:
> >In article <1003@pcsbst.pcs.com> horst@aida.pcs.com (horst kern) writes:
> >I've found that the easiest thing to do (so far) is to create a
> >single InputOnly window (you can use XCreateWindow() for this) that
> >goes over the entire screen (DefaultWidget() and DefaultHeight())
> 
> The problem seems to grow instead of being solved. Some e-mail from
> Mike Websters (my thanks to him) told me to map the InputOnly window
> on top of the one that I want it. You think it should be the whole
> screen. As you mention, it's an easy way - so far. It's of course not
> the best way, as people might have windows to other machines which are 
> not at all affected by the absence of one particular main loop. Even
> on one machine they might want to continue with another xterm while
> that machine is also busy with an application. 

Even though the window is as big as the screen, it will be clipped
by its parent window (the window of your toplevel widget),
so it won't affect any other applications.
It needs to be as big as the screen in case the user enlarges
the window while it is busy (exposing unbusy areas).

Here's some sample code:

    unsigned long valuemask;
    XSetWindowAttributes attributes;

    /*
     * Ignore device events while the busy cursor is displayed.
     */
    valuemask = CWDontPropagate | CWCursor;
    attributes.do_not_propagate_mask =  (KeyPressMask | KeyReleaseMask |
        ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
    attributes.cursor = XCreateFontCursor(XtDisplay(toplevel), XC_watch);

    /*
     * The window will be as big as the display screen, and clipped by
     * it's own parent window, so we never have to worry about resizing.
     */
    XCreateWindow(XtDisplay(toplevel), XtWindow(toplevel), 0, 0,
        WidthOfScreen(XtScreen(toplevel)), HeightOfScreen(XtScreen(toplevel)),
        (unsigned int) 0, CopyFromParent, InputOnly,
        CopyFromParent, valuemask, &attributes);

Andrew

--------------------------------------------------------------------------------
Andrew Wason                                        Bell Communications Research
aw@cellar.bae.bellcore.com                          Piscataway, NJ
bellcore!cellar!aw