chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / doors.c
1 /*
2  * $Id: doors.c,v 3.0 90/11/20 16:13:17 dme Exp Locker: dme $
3  *
4  * Copyright (c) 1990 Dave Edmondson.
5  * Copyright (c) 1990 Imperial College of Science, Technoology & Medicine
6  * All Rights Reserved.
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose and without fee is hereby granted, provided
10  * that the above copyright notice appear in all copies and that both that
11  * copyright notice and this permission notice appear in supporting
12  * documentation, and that the names of Dave Edmondson or Imperial College
13  * not be used in advertising or publicity pertaining to distribution of the
14  * software without specific, written prior permission. Dave Edmondson and
15  * Imperial College make no representations about the suitability of this
16  * software for any purpose.  It is provided "as is" without express or
17  * implied warranty.
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include "doors.h"
23 #include "screen.h"
24 #include "desktop.h"
25 #include "add_window.h"
26
27 extern void SetMapStateProp();
28 extern TwmDoor *door_add_internal();
29 extern void twmrc_error_prefix();
30
31 /* djhjr - 4/20/98 */
32 extern void HandleExpose();
33 extern void SetupWindow();
34
35 /* djhjr - 4/27/99 */
36 extern void AppletDown();
37
38 TwmDoor *door_add(name, position, destination)
39 char *name, *position, *destination;
40 {
41         int px, py, pw, ph, dx, dy;
42
43         /* djhjr - 4/26/96 */
44 /* djhjr - 8/11/98
45         * was 'Scr->use3Dborders' - djhjr - 8/11/98 *
46         int     bw = (Scr->BorderBevelWidth > 0) ? Scr->ThreeDBorderWidth : Scr->BorderWidth;
47 */
48         int     bw = Scr->BorderWidth;
49
50         JunkMask = XParseGeometry (position, &JunkX, &JunkY,
51                                    &JunkWidth, &JunkHeight);
52
53         /* we have some checking for negative (x,y) to do 
54            sorta taken from desktop.c by DSE */
55         if ((JunkMask & XNegative) == XNegative) {
56                 JunkX += Scr->MyDisplayWidth - JunkWidth - (2 * bw);
57                 }
58         if ((JunkMask & YNegative) == YNegative) {
59                 JunkY += Scr->MyDisplayHeight - JunkHeight - (2 * bw);
60                 }
61
62 /* allow position to be omitted - djhjr - 5/10/99
63         if ((JunkMask & (XValue | YValue)) !=
64             (XValue | YValue)) {
65                 twmrc_error_prefix();
66                 fprintf (stderr, "bad Door position \"%s\"\n", position);
67                 return NULL;
68         }
69 */
70
71         /* added this 'if (...) else' - djhjr - 5/10/99 */
72         if ((JunkMask & (XValue | YValue)) != (XValue | YValue))
73         {
74                 /* allow AddWindow() to position it - djhjr - 5/10/99 */
75                 JunkX = JunkY = -1;
76         }
77         else
78         {
79 /*              if (JunkX <= 0 || JunkY <= 0) {  */
80                 if (JunkX < 0 || JunkY < 0) { /* 0,0 accepted now -- DSE */
81                         twmrc_error_prefix();
82                         fprintf (stderr, "silly Door position \"%s\"\n", position);
83                         return NULL;
84                 }
85         }
86
87         /* they seemed ok */
88         px = JunkX;
89         py = JunkY;
90
91         if (JunkMask & WidthValue)
92                 pw = JunkWidth;
93         else
94                 /* means figure it out when you create the window */
95                 pw = -1;
96         if (JunkMask & HeightValue)
97                 ph = JunkHeight;
98         else
99                 ph = -1;
100
101         JunkMask = XParseGeometry (destination, &JunkX, &JunkY,
102                                    &JunkWidth, &JunkHeight);
103         if ((JunkMask & (XValue | YValue)) !=
104             (XValue | YValue)) {
105                 twmrc_error_prefix();
106                 fprintf (stderr, "bad Door destination \"%s\"\n", destination);
107                 return NULL;
108         }
109         if (JunkX < 0 || JunkY < 0) {
110                 twmrc_error_prefix();
111                 fprintf (stderr, "silly Door destination \"%s\"\n",
112                          destination);
113                 return NULL;
114         }
115         dx = JunkX;
116         dy = JunkY;
117
118         return (door_add_internal(name, px, py, pw, ph, dx, dy));
119 }
120
121 TwmDoor *door_add_internal(name, px, py, pw, ph, dx, dy)
122 char *name;
123 int px, py, pw, ph, dx, dy;
124 {
125         TwmDoor *new;
126
127         new = (TwmDoor *)malloc(sizeof(TwmDoor));
128         new->name = strdup(name);
129
130         /* this for getting colors */
131         new->class = XAllocClassHint();
132         new->class->res_name = new->name;
133         new->class->res_class = strdup(VTWM_DOOR_CLASS);
134
135         new->x = px;
136         new->y = py;
137         new->width = pw;
138         new->height = ph;
139         new->goto_x = dx;
140         new->goto_y = dy;
141
142         /* link into the list */
143         new->prev = NULL;
144         new->next = Scr->Doors;
145         if (Scr->Doors)
146                 Scr->Doors->prev = new;
147         Scr->Doors = new;
148
149         return (new);
150 }
151
152 void door_open(tmp_door)
153 TwmDoor *tmp_door;
154 {
155         Window w;
156
157         /* djhjr - 4/26/96 */
158 /* djhjr - 8/11/98
159         * was 'Scr->use3Dborders' - djhjr - 8/11/98 *
160         int     bw = (Scr->BorderBevelWidth > 0) ? Scr->ThreeDBorderWidth : Scr->BorderWidth;
161 */
162         int     bw = Scr->BorderWidth;
163
164         /* look up colours */
165         if (!GetColorFromList(Scr->DoorForegroundL,
166                               tmp_door->name,
167                               tmp_door->class, &tmp_door->colors.fore))
168                 tmp_door->colors.fore = Scr->DoorC.fore;
169         if (!GetColorFromList(Scr->DoorBackgroundL,
170                               tmp_door->name,
171                               tmp_door->class, &tmp_door->colors.back))
172                 tmp_door->colors.back = Scr->DoorC.back;
173
174         if (tmp_door->width < 0)
175 /* djhjr - 9/14/03 */
176 #ifndef NO_I18N_SUPPORT
177                 tmp_door->width = MyFont_TextWidth(&Scr->DoorFont,
178 #else
179                 tmp_door->width = XTextWidth(Scr->DoorFont.font,
180 #endif
181                                              tmp_door->name,
182                                              strlen(tmp_door->name))
183
184                         /* djhjr - 2/7/99 */
185                         + (Scr->DoorBevelWidth * 2)
186
187                         + SIZE_HINDENT;
188
189         if (tmp_door->height < 0)
190                 tmp_door->height = Scr->DoorFont.height
191
192                         /* djhjr - 2/7/99 */
193                         + (Scr->DoorBevelWidth * 2)
194
195                         + SIZE_VINDENT;
196
197         /* create the window */
198         w = XCreateSimpleWindow(dpy, Scr->Root,
199                                 tmp_door->x, tmp_door->y,
200                                 tmp_door->width, tmp_door->height,
201                                 bw,
202                                 tmp_door->colors.fore,
203                                 tmp_door->colors.back);
204         tmp_door->w = XCreateSimpleWindow(dpy, w,
205                                           0, 0,
206                                           tmp_door->width, tmp_door->height,
207                                           0,
208                                           tmp_door->colors.fore,
209                                           tmp_door->colors.back);
210
211 /* reworked to limit the minimum size of a door - djhjr - 3/1/99
212         if ((tmp_door->x < 0) || (tmp_door->y < 0)) {
213                 XSizeHints *hints = NULL;
214                 long ret;
215
216                  *
217                  * set the wmhints so that add_window() will allow
218                  * the user to place the window
219                  *
220                 if (XGetWMNormalHints(dpy, w, hints, &ret) > 0) {
221                         hints->flags = hints->flags &
222                                 (!USPosition & !PPosition);
223                         XSetStandardProperties(dpy, w,
224                                                tmp_door->class->res_name,
225                                                tmp_door->class->res_name,
226                                                None, NULL, 0, hints);
227                 }
228         } else {
229                 XSetStandardProperties(dpy, w,
230                                        tmp_door->class->res_name,
231                                        tmp_door->class->res_name,
232                                        None, NULL, 0, NULL);
233         }
234 */
235         {
236                 XSizeHints *hints = NULL;
237
238                 if (tmp_door->x < 0 || tmp_door->y < 0)
239                 {
240                         long ret;
241
242                         /*
243                          * set the wmhints so that add_window() will allow
244                          * the user to place the window
245                          */
246                         if (XGetWMNormalHints(dpy, w, hints, &ret) != 0)
247                                 hints->flags &= (!USPosition & !PPosition);
248                 }
249
250                 if (!hints) hints = XAllocSizeHints();
251
252                 hints->flags |= PMinSize;
253                 hints->min_width = tmp_door->width;
254                 hints->min_height = tmp_door->height;
255
256                 XSetStandardProperties(dpy, w,
257                                 tmp_door->class->res_name,
258                                 tmp_door->class->res_name,
259                                 None, NULL, 0, hints);
260         }
261
262         XSetClassHint(dpy, w, tmp_door->class);
263
264         /* set the name on both */
265         XStoreName(dpy, tmp_door->w, tmp_door->name);
266         XStoreName(dpy, w, tmp_door->name);
267
268         XDefineCursor( dpy, w, Scr->FrameCursor );/*RFB*/
269         XDefineCursor( dpy, tmp_door->w, Scr->DoorCursor );/*RFBCURSOR*/
270
271         /* moved these 'cuz AddWindow() will need 'em - djhjr - 11/15/01 */
272         /* store the address of the door on the window */
273         XSaveContext(dpy,
274                      tmp_door->w, DoorContext, (caddr_t) tmp_door);
275         XSaveContext(dpy,
276                      w, DoorContext, (caddr_t) tmp_door);
277
278         /* give to twm */
279         tmp_door->twin = AddWindow(w, FALSE, NULL);
280
281         SetMapStateProp(tmp_door->twin, NormalState);
282
283         /* interested in... */
284         XSelectInput(dpy, tmp_door->w, ExposureMask |
285                      ButtonPressMask | ButtonReleaseMask);
286
287         /* store the address of the door on the window */
288         XSaveContext(dpy,
289                      tmp_door->w,
290                      TwmContext, (caddr_t) tmp_door->twin);
291
292         /* map it */
293         XMapWindow(dpy, tmp_door->w);
294         XMapWindow(dpy, w);
295 }
296
297 void door_open_all()
298 {
299         TwmDoor *tmp_door;
300
301         for (tmp_door = Scr->Doors; tmp_door; tmp_door = tmp_door->next)
302                 door_open(tmp_door);
303 }
304
305 /*
306  * go into a door
307  */
308 void door_enter(w, d)
309 Window w;
310 TwmDoor *d;
311 {
312         int snapon; /* doors override real screen snapping - djhjr - 2/5/99 */
313
314         if (!d)
315                 /* find the door */
316                 if (XFindContext(dpy, w, DoorContext, (caddr_t *)&d)
317                     == XCNOENT)
318                         /* not a door ! */
319                         return;
320
321         /* go to it */
322         snapon = (int)Scr->snapRealScreen;
323         Scr->snapRealScreen = FALSE;
324         SetRealScreen(d->goto_x, d->goto_y);
325         Scr->snapRealScreen = (snapon) ? TRUE : FALSE;
326 }
327
328 /*
329  * delete a door
330  */
331 void door_delete(w, d)
332 Window w;
333 TwmDoor *d;
334 {       /*marcel@duteca.et.tudelft.nl*/
335         if (!d)
336                 /* find the door */
337                 if (XFindContext(dpy, w, DoorContext, (caddr_t *)&d)
338                     == XCNOENT)
339                         /* not a door ! */
340                         return;
341
342         /* unlink it: */
343         if (Scr->Doors == d)
344                 Scr->Doors = d->next;
345         if (d->prev != NULL)
346                 d->prev->next = d->next;
347         if (d->next != NULL)
348                 d->next->prev = d->prev;
349
350         /* djhjr - 4/27/99 */
351         AppletDown(d->twin);
352
353 /*
354  * Must this be done here ? Is it do by XDestroyWindow(),
355  * or by HandleDestroyNotify() in events.c, or should it
356  * it be done there ? M.J.E. Mol.
357  *
358  * It looks as though the contexts, at least, should be
359  * deleted here, maybe more, I dunno. - djhjr 2/25/99
360  */
361         XDeleteContext(dpy, d->w, DoorContext);
362         XDeleteContext(dpy, d->w,  TwmContext);
363         XDeleteContext(dpy, d->twin->w, DoorContext); /* ??? */
364         XUnmapWindow(dpy, d->w);
365         XUnmapWindow(dpy, w);
366         XDestroyWindow(dpy, w);
367         free(d->class->res_class); /* djhjr - 2/25/99 */
368         XFree(d->class);
369         free(d->name); /* djhjr - 2/25/99 */
370         free(d);
371 }
372
373 /*
374  * create a new door on the fly
375  */
376 void door_new()
377 {
378         TwmDoor *d;
379         char name[256];
380
381         sprintf(name, "+%d+%d", Scr->VirtualDesktopX, Scr->VirtualDesktopY);
382
383         d = door_add_internal(name, -1, -1, -1, -1,
384                               Scr->VirtualDesktopX, Scr->VirtualDesktopY);
385
386         door_open(d);
387 }
388
389 /*
390  * rename a door from cut buffer 0
391  *
392  * adapted from VTWM-5.2b - djhjr - 4/20/98
393  */
394 void
395 door_paste_name(w, d)
396 Window w;
397 TwmDoor* d;
398 {
399         int width, height, count;
400         char *ptr;
401 /* djhjr - 8/11/98
402         * was 'Scr->use3Dborders' - djhjr - 8/11/98 *
403         int     bw = (Scr->BorderBevelWidth > 0) ? Scr->ThreeDBorderWidth : Scr->BorderWidth;
404 */
405         /* added initialization and test - djhjr - 3/1/99 */
406         int bw = 0;
407         if (Scr->BorderBevelWidth) bw = Scr->BorderWidth;
408  
409         if (!d)
410                 if (XFindContext(dpy, w, DoorContext, (caddr_t *)&d) == XCNOENT)
411                         return;
412
413         /* sanity check - djhjr - 10/31/00 */
414         if (!(ptr = XFetchBytes(dpy, &count)) || count == 0) return;
415         if (count > 128) count = 128;
416
417         if (d->name)
418                 d->name = realloc(d->name, count + 1);
419         else
420                 d->name = malloc(count + 1);
421
422         sprintf(d->name, "%*s", count, ptr);
423         XFree(ptr);
424
425         /* djhjr - 1/14/99 */
426         XClearWindow(dpy, d->w);
427
428         /* added 'Scr->DoorBevelWidth * 2' - djhjr - 2/7/99 */
429 /* djhjr - 9/14/03 */
430 #ifndef NO_I18N_SUPPORT
431         width = MyFont_TextWidth(&Scr->DoorFont, d->name, count) +
432 #else
433         width = XTextWidth(Scr->DoorFont.font, d->name, count) +
434 #endif
435                         SIZE_HINDENT + (Scr->DoorBevelWidth * 2);
436         height = Scr->DoorFont.height + SIZE_VINDENT + (Scr->DoorBevelWidth * 2);
437
438         /* limit the size of a door - djhjr - 3/1/99 */
439         d->twin->hints.flags |= PMinSize;
440         d->twin->hints.min_width = width;
441         d->twin->hints.min_height = height;
442
443         SetupWindow(d->twin, d->twin->frame_x, d->twin->frame_y,
444                         width + 2 * bw, height + d->twin->title_height + 2 * bw, -1);
445
446         HandleExpose();
447 }
448