1 /*
2  *  Copyright (C) 1995, 1996  Karl-Johan Johnsson.
3  */
4 
5 #include <X11/IntrinsicP.h>
6 #include <X11/StringDefs.h>
7 
8 #include "Compat.h"
9 #include "Util.h"
10 #include "CloseShP.h"
11 
12 static XtResource resources[] = {
13     {XtNinput, XtCInput, XtRBool, sizeof(Bool),
14      XtOffsetOf(CloseShellRec, wm.wm_hints.input),
15      XtRImmediate, (XtPointer)True},
16     {XtNallowShellResize, XtCAllowShellResize, XtRBoolean, sizeof(Boolean),
17      XtOffsetOf(CloseShellRec, shell.allow_shell_resize),
18      XtRImmediate, (XtPointer)True},
19 #define offset(field) XtOffsetOf(CloseShellRec, close_shell.field)
20     {XtNcursor, XtCCursor, XtRCursor, sizeof(Cursor),
21      offset(cursor), XtRString, (XtPointer)"top_left_arrow"},
22     {XtNcloseCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
23      offset(close_callback), XtRImmediate, (XtPointer)NULL},
24 #undef offset
25 };
26 
27 static void	ClassPartInitialize(WidgetClass);
28 static void	Realize(Widget, XtValueMask*, XSetWindowAttributes*);
29 static Boolean	SetValues(Widget, Widget, Widget, ArgList, Cardinal*);
30 
31 static void	close_window(Widget, XEvent*, String*, Cardinal*);
32 
33 static XtActionsRec actions[] = {
34     {"close-window",	close_window},
35 };
36 
37 static char translations[] =
38 "<Message>WM_PROTOCOLS:	close-window() \n";
39 
40 CloseShellClassRec closeShellClassRec = {
41     {                                   /* core fields                  */
42         (WidgetClass) &transientShellClassRec, /* superclass            */
43         "CloseShell",                   /* class_name                   */
44         sizeof(CloseShellRec),	        /* widget_size                  */
45         NULL,                           /* class_initialize             */
46         ClassPartInitialize,		/* class_part_initialize        */
47         FALSE,                          /* class_inited                 */
48         NULL,				/* initialize                   */
49         NULL,                           /* initialize_hook              */
50         Realize,                        /* realize                      */
51         actions,                        /* actions                      */
52         XtNumber(actions),              /* num_actions                  */
53         resources,                      /* resources                    */
54         XtNumber(resources),            /* num_resources                */
55         NULLQUARK,                      /* xrm_class                    */
56         TRUE,                           /* compress_motion              */
57 	FALSE,				/* compress_exposure		*/
58         TRUE,                           /* compress_enterleave          */
59         FALSE,                          /* visible_interest             */
60         NULL,				/* destroy                      */
61         XtInheritResize,                /* resize                       */
62         NULL,	                        /* expose                       */
63         SetValues,                      /* set_values                   */
64         NULL,                           /* set_values_hook              */
65         XtInheritSetValuesAlmost,       /* set_values_almost            */
66         NULL,                           /* get_values_hook              */
67         NULL,                           /* accept_focus                 */
68         XtVersion,                      /* version                      */
69         NULL,                           /* callback_private             */
70         translations,                   /* tm_table                     */
71         NULL,                           /* query_geometry               */
72         XtInheritDisplayAccelerator,    /* display_accelerator          */
73         NULL                            /* extension                    */
74     },
75     {					/* composite fields		*/
76 	XtInheritGeometryManager,	/* geometry_manager		*/
77 	XtInheritChangeManaged,		/* change_managed		*/
78 	XtInheritInsertChild,		/* insert_child			*/
79 	XtInheritDeleteChild,		/* delete_child			*/
80 	NULL,				/* extension			*/
81     },
82     {					/* shell fields			*/
83 	NULL,				/* extension			*/
84     },
85     {					/* wm shell fields		*/
86 	NULL,				/* extension			*/
87     },
88     {					/* vendor shell fields		*/
89 	NULL,				/* extension			*/
90     },
91     {					/* transient shell fields	*/
92 	NULL,				/* extension			*/
93     },
94     {					/* close_shell fields		*/
95 	NULL,				/* close_window			*/
96 	NULL,				/* extension			*/
97     }
98 };
99 
100 WidgetClass closeShellWidgetClass = (WidgetClass)&closeShellClassRec;
101 
102 /*************************************************************************/
103 
close_window(Widget gw,XEvent * event,String * params,Cardinal * no_params)104 static void close_window(Widget gw, XEvent *event,
105 			 String *params, Cardinal *no_params)
106 {
107     CloseShellWidget		w = (CloseShellWidget)gw;
108     CloseShellWidgetClass	class;
109 
110     class = (CloseShellWidgetClass)XtClass(w);
111     if (!class->close_shell_class.close_window) {
112 	XtCallCallbackList((Widget)w, w->close_shell.close_callback, NULL);
113 	return;
114     }
115 
116     if (event->type == ClientMessage) {
117 	Display	*disp = XtDisplay(w);
118 	Atom	wm_delete_window = intern_atom(disp, "WM_DELETE_WINDOW");
119 	Atom	wm_protocols     = intern_atom(disp, "WM_PROTOCOLS");
120 
121 	if (event->xclient.message_type == wm_protocols &&
122 	    event->xclient.data.l[0]    == wm_delete_window)
123 	    class->close_shell_class.close_window((Widget)w);
124     }
125 }
126 
127 /*************************************************************************/
128 
ClassPartInitialize(WidgetClass gclass)129 static void ClassPartInitialize(WidgetClass gclass)
130 {
131     CloseShellWidgetClass	class, super;
132 
133     class = (CloseShellWidgetClass)gclass;
134     super = (CloseShellWidgetClass)class->core_class.superclass;
135 
136     if (class->close_shell_class.close_window == XtInheritCloseWindow)
137 	class->close_shell_class.close_window =
138 	    super->close_shell_class.close_window;
139 }
140 
Realize(Widget gw,XtValueMask * mask,XSetWindowAttributes * attributes)141 static void Realize(Widget gw, XtValueMask *mask,
142 		    XSetWindowAttributes *attributes)
143 {
144     CloseShellWidget	w = (CloseShellWidget)gw;
145     Display		*disp = XtDisplay(w);
146     Atom		wm_delete_window;
147 
148     if (w->close_shell.cursor != None) {
149 	*mask |= CWCursor;
150 	attributes->cursor = w->close_shell.cursor;
151     }
152 
153     transientShellWidgetClass->core_class.realize((Widget)w, mask, attributes);
154 
155     wm_delete_window = intern_atom(disp, "WM_DELETE_WINDOW");
156     XSetWMProtocols(disp, XtWindow(w), &wm_delete_window, 1);
157 }
158 
SetValues(Widget gcurrent,Widget grequest,Widget gnew,ArgList args,Cardinal * num_args)159 static Boolean SetValues(Widget gcurrent,
160 			 Widget grequest,
161 			 Widget gnew,
162 			 ArgList args,
163 			 Cardinal *num_args)
164 {
165     Boolean		redisplay = False;
166     CloseShellWidget	new       = (CloseShellWidget)gnew;
167     CloseShellWidget	current   = (CloseShellWidget)gcurrent;
168 
169     if (new->close_shell.cursor != current->close_shell.cursor)
170 	CloseShellSetCursor((Widget)new, new->close_shell.cursor);
171 
172     return redisplay;
173 }
174 
175 /*************************************************************************/
176 
CloseShellSetCursor(Widget gw,Cursor cursor)177 void CloseShellSetCursor(Widget gw, Cursor cursor)
178 {
179     CloseShellWidget	w = (CloseShellWidget)gw;
180     Display		*disp = XtDisplay(w);
181     Window		win = XtWindow(w);
182 
183     w->close_shell.cursor = cursor;
184     if (XtIsRealized((Widget)w))
185 	XDefineCursor(disp, win, cursor);
186 }
187