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