1 /*  Part of XPCE --- The SWI-Prolog GUI toolkit
2 
3     Author:        Jan Wielemaker and Anjo Anjewierden
4     E-mail:        jan@swi.psy.uva.nl
5     WWW:           http://www.swi.psy.uva.nl/projects/xpce/
6     Copyright (c)  1995-2011, University of Amsterdam
7     All rights reserved.
8 
9     Redistribution and use in source and binary forms, with or without
10     modification, are permitted provided that the following conditions
11     are met:
12 
13     1. Redistributions of source code must retain the above copyright
14        notice, this list of conditions and the following disclaimer.
15 
16     2. Redistributions in binary form must reproduce the above copyright
17        notice, this list of conditions and the following disclaimer in
18        the documentation and/or other materials provided with the
19        distribution.
20 
21     THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22     "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23     LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24     FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25     COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26     INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
27     BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28     LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
29     CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30     LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
31     ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32     POSSIBILITY OF SUCH DAMAGE.
33 */
34 
35 #include <h/kernel.h>
36 #include <h/graphics.h>
37 
38 static status
initialiseDisplayManager(DisplayManager dm)39 initialiseDisplayManager(DisplayManager dm)
40 { assign(dm, members, newObject(ClassChain, EAV));
41   assign(dm, current, newObject(ClassChain, EAV));
42 
43   protectObject(dm);
44 
45   succeed;
46 }
47 
48 
49 status
appendDisplayManager(DisplayManager dm,DisplayObj d)50 appendDisplayManager(DisplayManager dm, DisplayObj d)
51 { appendChain(dm->members, d);
52   if ( emptyChain(dm->current) )
53     prependChain(dm->current, d);
54 
55   succeed;
56 }
57 
58 
59 DisplayObj
getMemberDisplayManager(DisplayManager dm,Name address)60 getMemberDisplayManager(DisplayManager dm, Name address)
61 { Cell cell;
62 
63   for_cell(cell, dm->members)
64   { DisplayObj d = cell->value;
65 
66     if ( d->address == address )
67       answer(d);
68   }
69 
70   fail;
71 }
72 
73 
74 static status
currentDisplayManager(DisplayManager dm,DisplayObj d)75 currentDisplayManager(DisplayManager dm, DisplayObj d)
76 { return prependChain(dm->current, d);
77 }
78 
79 
80 static DisplayObj
getCurrentDisplayManager(DisplayManager dm)81 getCurrentDisplayManager(DisplayManager dm)
82 { if ( emptyChain(dm->current) )
83   { realiseClass(ClassDisplay);
84 
85     if ( emptyChain(dm->current) )
86     { errorPce(dm, NAME_noCurrentDisplay);
87       fail;
88     }
89   }
90 
91   answer(dm->current->head->value);
92 }
93 
94 
95 static status
popCurrentDisplayManager(DisplayManager dm)96 popCurrentDisplayManager(DisplayManager dm)
97 { if ( getSizeChain(dm->current) == ONE )
98     return errorPce(dm, NAME_stackEmpty, NAME_current);
99 
100   return deleteHeadChain(dm->current);
101 }
102 
103 
104 DisplayObj
CurrentDisplay(Any obj)105 CurrentDisplay(Any obj)
106 { DisplayObj d;
107 
108   if ( instanceOfObject(obj, ClassGraphical) &&
109        (d = getDisplayGraphical((Graphical) obj)) )
110     return d;
111 
112   return getCurrentDisplayManager(TheDisplayManager());
113 }
114 
115 
116 static PceWindow
getWindowOfLastEventDisplayManager(DisplayManager dm)117 getWindowOfLastEventDisplayManager(DisplayManager dm)
118 { PceWindow sw = WindowOfLastEvent();
119 
120   answer(sw);
121 }
122 
123 
124 static status
eventQueuedDisplayManager(DisplayManager dm)125 eventQueuedDisplayManager(DisplayManager dm)
126 { Cell cell;
127 
128   for_cell(cell, dm->members)
129   { if ( ws_events_queued_display(cell->value) )
130       succeed;
131   }
132 
133   fail;
134 }
135 
136 #define TestBreakDraw(dm) \
137 	if ( dm->test_queue == ON && \
138 	     eventQueuedDisplayManager(dm) ) \
139 	  fail;
140 
141 static status
redrawDisplayManager(DisplayManager dm)142 redrawDisplayManager(DisplayManager dm)
143 { if ( ChangedWindows && !emptyChain(ChangedWindows) )
144   { PceWindow sw = WindowOfLastEvent();
145 
146     obtainClassVariablesObject(dm);
147 
148     TestBreakDraw(dm);
149     if ( sw && memberChain(ChangedWindows, sw) )
150       RedrawWindow(sw);
151 
152     while( !emptyChain(ChangedWindows) )
153     { TestBreakDraw(dm);
154 
155       for_chain(ChangedWindows, sw,
156 		{ if ( !instanceOfObject(sw, ClassWindowDecorator) )
157 		    RedrawWindow(sw);
158 		});
159 
160       TestBreakDraw(dm);
161 
162       for_chain(ChangedWindows, sw,
163 		{ if ( instanceOfObject(sw, ClassWindowDecorator) )
164 		    RedrawWindow(sw);
165 		});
166     }
167   }
168 
169   succeed;
170 }
171 
172 
173 status
RedrawDisplayManager(DisplayManager dm)174 RedrawDisplayManager(DisplayManager dm)
175 { return sendv(dm, NAME_redraw, 0, NULL);
176 }
177 
178 
179 status
dispatchDisplayManager(DisplayManager dm,Int fd,Int timeout)180 dispatchDisplayManager(DisplayManager dm, Int fd, Int timeout)
181 { if ( isDefault(timeout) )
182     timeout = toInt(250);
183 
184   return ws_dispatch(fd, timeout);
185 }
186 
187 
188 static status
dispatch_events(int fd,int timeout)189 dispatch_events(int fd, int timeout)
190 { return dispatchDisplayManager(TheDisplayManager(),
191 				fd >= 0 ? toInt(fd) : NIL,
192 				toInt(timeout));
193 }
194 
195 		/********************************
196 		*             VISUAL		*
197 		********************************/
198 
199 static Chain
getContainsDisplayManager(DisplayManager dm)200 getContainsDisplayManager(DisplayManager dm)
201 { answer(dm->members);
202 }
203 
204 
205 		 /*******************************
206 		 *	     GLOBAL		*
207 		 *******************************/
208 
209 DisplayManager
TheDisplayManager()210 TheDisplayManager()
211 { static DisplayManager dm = NULL;
212 
213   if ( !dm )
214     dm = findGlobal(NAME_displayManager);
215 
216   return dm;
217 }
218 
219 
220 		 /*******************************
221 		 *	 CLASS DECLARATION	*
222 		 *******************************/
223 
224 /* Type declarations */
225 
226 static char *T_dispatch[] =
227         { "file_descriptor=[int]", "milliseconds=[int]*" };
228 
229 /* Instance Variables */
230 
231 static vardecl var_displayManager[] =
232 { IV(NAME_members, "chain", IV_GET,
233      NAME_display, "Available displays"),
234   IV(NAME_current, "chain", IV_NONE,
235      NAME_current, "Stack with current displays"),
236   IV(NAME_testQueue, "bool", IV_BOTH,
237      NAME_event, "Test queue in event-loop")
238 };
239 
240 /* Send Methods */
241 
242 static senddecl send_displayManager[] =
243 { SM(NAME_initialise, 0, NULL, initialiseDisplayManager,
244      DEFAULT, "Create the display manager"),
245   SM(NAME_current, 1, "display", currentDisplayManager,
246      NAME_current, "Make display the current display"),
247   SM(NAME_popCurrent, 0, NULL, popCurrentDisplayManager,
248      NAME_current, "Pop the current stack"),
249   SM(NAME_append, 1, "display", appendDisplayManager,
250      NAME_display, "Attach a new display to the manager"),
251   SM(NAME_dispatch, 2, T_dispatch, dispatchDisplayManager,
252      NAME_event, "Dispatch events for 1/4th second"),
253   SM(NAME_redraw, 0, NULL, redrawDisplayManager,
254      NAME_event, "Flush all pending changes to the screen")
255 };
256 
257 /* Get Methods */
258 
259 static getdecl get_displayManager[] =
260 { GM(NAME_contains, 0, "chain", NULL, getContainsDisplayManager,
261      DEFAULT, "Contained displays"),
262   GM(NAME_current, 0, "display", NULL, getCurrentDisplayManager,
263      NAME_current, "Get the current display"),
264   GM(NAME_member, 1, "display", "name", getMemberDisplayManager,
265      NAME_display, "Find display for specified address"),
266   GM(NAME_windowOfLastEvent, 0, "window", NULL, getWindowOfLastEventDisplayManager,
267      NAME_event, "Find window that received last event")
268 };
269 
270 /* Resources */
271 
272 static classvardecl rc_displayManager[] =
273 { RC(NAME_testQueue, "bool", "@on", NULL)
274 };
275 
276 /* Class Declaration */
277 
278 ClassDecl(displayManager_decls,
279           var_displayManager, send_displayManager,
280 	  get_displayManager, rc_displayManager,
281           0, NULL,
282           "$Rev$");
283 
284 
285 status
makeClassDisplayManager(Class class)286 makeClassDisplayManager(Class class)
287 { declareClass(class, &displayManager_decls);
288 
289   globalObject(NAME_displayManager, ClassDisplayManager, EAV);
290   DispatchEvents = dispatch_events;
291 
292   succeed;
293 }
294 
295