From: kr1@csug.cs.reading.ac.uk (Kevin Richards [METOFF])
Newsgroups: comp.lang.pop
Subject: X and Pop
Keywords: pwm OpenLook X
Date: 17 Nov 92 14:33:47 GMT
Reply-To: kr1@csug.cs.reading.ac.uk
Organization: Dept. of Comp. Sci., University of Reading


hello,

Calling all those people (yes both of you), who know anything about X and pop11.
We have been trying to emulate pwm, under X, and  have built up a number of 
procedures which do pwm things, only using the OpenLook widget set.

The eventhandling is carried out similarly to pop using pwm_eventhandler,
two procedures which we are trying to get right are pwm_make_menu, 
and pwm_display_menu (The code for these procedures is included at the end). The 
question I want answering is why pwm_display_menu will work from a command line,
but fail when used in the eventhandler 
	i.e. -

	: pwm_make_gfxwin('tst',100,100) -> win;
	: procedure(ev);
  	pwm_display_menu('Test\tHello\tWorld\t') =>
  	endprocedure -> pwm_eventhandler(win,"press");

/* Okay calling it on its own works */
	: pwm_display_menu('Test\tHello\tWorld\t') =>
	** 1

But when you press a button in 'win' the menu is created but appears blank
and no events are processed. Pop siezes up and you need a kill -QUIT to get
rid of the menu.

When you remove the loop from pwm_display_menu, it works (but we don't get any response) is there a better way of doing it. Or is there a simple fix


	
	Cheers Kev
	

  ____________________________________________________________________
  Kevin Richards                              K.Richards@reading.ac.uk        

                University of Reading, Whiteknights, 
                       Reading, Berkshire, Uk

                    Phone +44 734 875123 ext 7642




/* CODE ----------------------------------------------------------------*/
/*  --- Copyright Intelligent Systems Group at University of Reading --------
    --- 1991.  All rights reserved. -----------------------------------------
 > File:           pwm_eventhandler.p
 > Purpose:        provide an event handler for X pwm windows
 > Documentation:  HELP * dummy
 > Related Files:  MAN  * rcsintro
 > RCS Information
 >     $Author: adw $
 >     $Date: 92/11/14 18:14:44 $
 >     $RCSfile: pwm_eventhandler.p,v $
 >     $Revision: 1.2 $
 >     $State: Exp $
 >     $Locker:  $

         CONTENTS - (Use <ENTER> gd to access required procedure)

 define pwm_inputcatcher(ev);
 define handle_button_event(widget,client,call_data);
 define handle_resize_event(widget,client,call_data);
 define handle_keyboard_event(widget,client,call_data);
 define global pwm_eventhandler(widget,type)->proc;
 define updaterof global pwm_eventhandler(proc,widget,type);

 */

uses pwm_windowtype;
uses popxlib;
uses xt_widget;
uses xt_callback;
uses xt_event;
uses XolConstants;
uses xlib;
uses XWindowAttributes;
uses XHouseKeeping;
uses XWindowConstants;
uses XKeyboard;
uses XEvents;
loadinclude xpt_xevent.ph;




section;

section $-library XLookupString => pwm_eventhandler handle_resize_event handle_keyboard_event handle_button_event handle_move_event handle_status_event;
section $-library$-pwmlib XLookupString => pwm_eventhandler handle_resize_event handle_keyboard_event handle_button_event handle_move_event handle_status_event;

global vars  pwm_last_button = 1;
global vars  pwmreport = false;

;;;defined in pwm_track_mouse
vars report_motion   = false;
vars tracking_motion = false;
vars handle_tracking exit_tracking;

define global pwm_inputcatcher(ev);
lvars ev message;
    switchon subscrv(1,ev) ==
        case "quitrequest" then

                pwm_kill_window(pwminputsource);
                pwminputsource <> ' killed';
        case "release"
        orcase "press"
        orcase "move"
        orcase "mouseexit"
        orcase "character" then
            ('message ' >< ev) >< ' received from ' >< pwminputsource;
            else
            false;
    endswitchon  -> message;

    if message and pwmreport then
            if vedediting then
                vedputmessage(message);
            else
                pr(';;; ' <> message <> '\n');
            endif;
    endif;
enddefine;


vars win_proc_table = newproperty([],32,false,"tmparg");

define handle_move_event(widget,client,call_data);
    lvars widget,button,client,ev,proc_table,proc,call_data;

    if (pwm_last_button>0) and (exacc :XEvent call_data.type == MotionNotify)
    then
        {%
            "move",
            abs(pwm_last_button),
            exacc :XMotionEvent call_data.x,
            exacc :XMotionEvent call_data.y
        %} -> ev;

        ;;;get the widgets evant handlers
        win_proc_table(pwm_widget_windows(widget)) -> proc_table;

        if tracking_motion then
            handle_tracking(ev);

            if report_motion then
                unless proc_table and (proc_table("move")->> proc) then
                    pwm_inputcatcher -> proc;
                endunless;

                ;;;set the widget as the input source
                pwm_widget_windows(widget) -> pwminputsource;
                chain(ev,proc);
            endif;
        endif;
    endif;
enddefine;

define handle_button_event(widget,client,call_data);
lvars widget,button,client,ev,proc_table,proc,call_data,type,x,y;
    ;;;convert button to a pop int
    if exacc :XButtonEvent call_data.type =  5 then
        ( exacc :XButtonReleasedEvent call_data.button ) * (-1)-> button;
        exacc :XButtonReleasedEvent call_data.x -> x;
        exacc :XButtonReleasedEvent call_data.y -> y;
    else
        exacc :XButtonPressedEvent call_data.button -> button;
        exacc :XButtonPressedEvent call_data.x -> x;
        exacc :XButtonPressedEvent call_data.y -> y;
    endif;
    button -> pwm_last_button;

    if button < 0 then
        if x =< 0 or x >= XptValue(widget,XtN width, "short")
        or y =< 0 or y >= XptValue(widget,XtN height, "short")
        then
            "mouseexit" -> type;
            0 ->> x -> y;
        else
            "release" -> type;
        endif;
    else
        "press" -> type;
    endif;

    {% type, abs(button), x, y %} -> ev;

    if tracking_motion then
        exit_tracking(ev);
    endif;

    ;;;get the widgets evant handlers
    win_proc_table(pwm_widget_windows(widget)) -> proc_table;

    unless proc_table and (proc_table(type)->> proc) then
        pwm_inputcatcher -> proc;
    endunless;

    ;;;set the widget as the input source
    pwm_widget_windows(widget) -> pwminputsource;

    proc(ev);
enddefine;

define handle_status_event(widget,client,call_data);
lvars widget,button,client,ev,proc_table,proc,call_data;
    ;;; Windows opening and closing and destroying
    ;;; pr('Status');
    switchon exacc :XEvent call_data.type ==
    case FocusIn then
        {% "focusin",
            0,0,0
        %} -> ev;
            pwm_widget_windows(widget) -> pwminputsource;
                ;;;get the widgets evant handlers
                win_proc_table(pwm_widget_windows(widget)) -> proc_table;
                unless proc_table and (proc_table("focusin")->> proc) then
                        pwm_inputcatcher -> proc;
                endunless;

            ;;;set the widget as the input source
            pwm_widget_windows(widget) -> pwminputsource;
            chain(ev,proc);
    case FocusOut then
        {% "focusout",
            0,0,0
        %} -> ev;
                ;;;get the widgets evant handlers
            pwm_widget_windows(widget) -> pwminputsource;
                win_proc_table(pwm_widget_windows(widget)) -> proc_table;
            unless proc_table and (proc_table("focusout")->> proc) then
                pwm_inputcatcher -> proc;
            endunless;
            chain(ev,proc);
    case DestroyNotify then
        {%
          "quitrequest",
          0,0,0
        %} -> ev;
        pr('Destroy\n');

            ;;;get the widgets evant handlers
            win_proc_table(pwm_widget_windows(widget)) -> proc_table;
            unless proc_table and (proc_table("quitrequest")->> proc) then
                pwm_inputcatcher -> proc;
            endunless;
            chain(ev,proc);
    else
        ;;; ignore
    endswitchon;

enddefine;


define handle_resize_event(widget,client,call_data);
lvars widget,button,client,ev,proc_table,proc,call_data;

    {%
        "resized",
        abs(pwm_last_button),
    exacc :XResizeRequestEvent call_data.width,
        exacc :XResizeRequestEvent call_data.height
    %} -> ev;

    ;;;get the widgets evant handlers
    win_proc_table(pwm_widget_windows(widget)) -> proc_table;

    unless proc_table and (proc_table("resized")->> proc) then
        pwm_inputcatcher -> proc;
    endunless;

    ;;;set the widget as the input source
    pwm_widget_windows(widget) -> pwminputsource;

    chain(ev,proc);
enddefine;

define handle_keyboard_event(widget,client,call_data);
lvars widget,client,ev,proc_table,proc,call_data,i,key;
lvars temps = inits(1);

    ;;;convert button to a pop int
    if (XLookupString(call_data,temps,1,NULLptr,NULLptr) == 1) then
            temps(1) -> key;


            {%
                "character",
                key, 0, 0
                %} -> ev;

            ;;;get the widgets evant handlers
            win_proc_table(pwm_widget_windows(widget)) -> proc_table;

            unless proc_table and (proc_table("character")->> proc) then
                pwm_inputcatcher -> proc;
            endunless;

            ;;;set the widget as the input source
            pwm_widget_windows(widget) -> pwminputsource;

            if proc.isprocedure then
                proc(ev);
            else
                valof(proc)(ev);
            endif;
    endif;
enddefine;

define global pwm_eventhandler(pwm_id,type)->proc;
lvars type,proc,proc_table;

    ;;;get the widgets evant handlers
    win_proc_table(pwm_id) -> proc_table;

    unless proc_table and (proc_table(type)->> proc) then
        pwm_inputcatcher -> proc;
    endunless;
enddefine;

define updaterof global pwm_eventhandler(proc,pwm_id,type);
lvars type,proc,proc_table;
    ;;;get the widgets evant handlers
    win_proc_table(pwm_id) -> proc_table;

    unless proc_table then
        newproperty([],10,false,"tmparg") -> proc_table;
        proc_table -> win_proc_table(pwm_id);
    endunless;

    proc -> proc_table(type);
enddefine;

endsection;
endsection;

endsection;

/*----------------------------------------------------------------------------*/



section;

section $-library => pwm_make_menu  pwm_menu_value;
section $-library$-pwmlib => pwm_make_menu  pwm_menu_value;

uses xt_widget;
uses xt_widgetclass;
uses xt_widgetinfo;
uses xt_trans;
uses xt_action;
uses xt_event;
uses xt_popup;
uses xt_callback;
uses xlib;
uses pwm_make_execitem;
uses pwm_eventhandler;
uses conspwmitem;

loadinclude xt_constants;


define parse_menu_string(string) -> title -> labels;
lvars l_text = [],pos,len,line,height,start,i;
        true -> pos;
        1 -> start;
        length(string) -> len;
        while (start <= len) do
                issubstring_lim('\t',start,len,false,string) -> pos;
                if not(pos) then
                        substring(start,len-start+1,string) -> line;
                        start+len+1-start -> start;
                else
                        substring(start,pos-start,string) -> line;
                        pos+1 -> start;
                endif;
                l_text <> [^line] -> l_text;
        endwhile;
	
	;;; Extract title
	hd(l_text) -> title;
	tl(l_text) -> labels;
	
enddefine;

define menu_wrapper(widget,clientdata,calldata,item);
lvars widget,clientdata,calldata,item;
	clientdata -> ((item.pi_other)(1));
enddefine;

define pwm_menu_value(item);
lvars item;
	return((item.pi_other)(1));
enddefine;


define updaterof pwm_menu_value(value,item);
lvars value,item;
dlocal 0 %,false -> (item.pi_other)(1) %;
	if value and not((item.pi_other)(1)) then
		unless value.isnumber then 1 -> value; endunless;
		value -> (item.pi_other)(1);
	endif;
enddefine;

define global pwm_make_menu(string) -> item;
lvars width, event;
lvars hsize,temp,trans,lines,i,item;
lvars menu_widget,widget;
lvars shell,popup_shell,menupane,control;

    fast_XtAppCreateShell('dummy','dummy_class',basewindow_class,
			XptDefaultDisplay,
                    	XptArgList([{input ^true}])) -> shell;

    parse_menu_string(string) -> title -> labels;

    XtCreatePopupShell(title,menu_class,
			shell,
			XptArgList([{input ^true}
				    {pushpin ^OL_NONE}
				    {XtNmenuAugment ^false}
				    {title ^title}
				])) -> menu_widget;


   conspwmitem("menu",pwm_menu_value,menu_widget,false,false) -> item;
   XtRealizeWidget(menu_widget);
   XptValue(menu_widget,XtN menuPane, TYPESPEC(:XptWidget))  -> menupane;

   {% false,
	XtCreateManagedWidget('ControlArea',control_class,menupane,
		XptArgList([{layoutType ^OL_FIXEDCOLS}])) ->> control;
	for i from 1 to length(labels) do
		XtCreateManagedWidget(labels(i),fancy_exec_class,control,XptArgList([])) ->> widget;
		XtAddCallback(widget,'select', menu_wrapper(%item%),i);
	endfor;
   %} -> item.pi_other;

  "menu" -> pwmidtype(item);

enddefine;

endsection;
endsection;

endsection;




/* ---------------------------------------------------------------------------*/



section;

uses XHouseKeeping;

section $-library Xsync => pwm_display_menu  ;
section $-library$-pwmlib Xsync  => pwm_display_menu;

uses pwm_make_menu;
uses conspwmitem;



define global pwm_display_menu(menu) ->response;

   unless ispwmitem(menu) then
	pwm_make_menu(menu) -> menu;
   endunless;

   false -> pwm_menu_value(menu);
   OlMenuPost(pi_widget(menu));

   XSync(XptDefaultDisplay,0);

   ;;; Loop until event recieved
   while(pwm_menu_value(menu) == false) do
	syssleep(100);
		;;; Wait
   endwhile;

   pwm_menu_value(menu)-> response;

enddefine;

endsection;
endsection;

endsection;