1 /*
2 * Copyright (C) 2003 Sasha Vasko
3 * Copyright (C) 1996 Frank Fejes
4 * Copyright (C) 1996 Alfredo Kojima
5 * Copyright (C) 1995 Bo Yang
6 * Copyright (C) 1993 Robert Nation
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 *
22 */
23
24 #define LOCAL_DEBUG
25
26 #include "../../configure.h"
27
28 #include "asinternals.h"
29 #include "../../libAfterConf/afterconf.h"
30
31 /********************************************************************/
32 /* ASWindow frame decorations : */
33 /********************************************************************/
34 /* window frame decoration consists of :
35 Top level window
36 4 canvases - one for each side :
37 Top or left canvas contains titlebar+ adjusen frame side+corners if any
38 Bottom or right canvas contains sidebar which is the same as south frame side with corners
39 Remaining two canvasses contain east and west frame sides only ( if any );
40 Canvasses surround main window and its sizes are actually the frame size.
41 * For each frame part and title we have separate TBarData structure. ( 9 total )
42 * In windows with vertical title we keep the orientation of canvases but turn
43 * tbars counterclockwise 90 degrees. As The result Title tbar will be shown on FR_W canvas,
44 * instead of FR_N canvas. Frame parts will be shown on the following canvases :
45 * Frame part | Canvas
46 * --------------+-----------
47 * FR_N FR_W
48 * FR_NE FR_W
49 * FR_E FR_N
50 * FR_SE FR_E
51 * FR_S FR_E
52 * FR_SW FR_E
53 * FR_W FR_S
54 * FR_NW FR_W
55 *
56 * That has to be taken on account whenever we have to associate tbars and canvases,
57 * like in moving/resizing, redrawing, hiliting, pressing and context lookup
58 *
59 * Icon is drawn on one or two canvases. If separate button titles are selected and Icon title
60 * is allowed for this style, then separate canvas will be created for the titlebar.
61 * Respectively icon_title_canvas will be different then icon_canvas. In all other cases
62 * Icon_title_canvas will be the same as icon_canvas.
63 */
64
65 static int NormalX, NormalY;
66 static unsigned int NormalWidth, NormalHeight;
67 /* Mirror Note :
68 *
69 * For the purpose of sizing/placing left and right sides and corners - we employ somewhat
70 * twisted logic - we mirror sides over lt2rb diagonal in case of
71 * vertical title orientation. That allows us to apply simple x/y switching instead of complex
72 * calculations. Note that we only do that for placement purposes. Contexts and images are
73 * still taken from MyFrame parts as if it was rotated counterclockwise instead of mirrored.
74 */
75
76 ASOrientation HorzOrientation = {
77 {C_FrameN, C_FrameE, C_FrameS, C_FrameW, C_FrameNW, C_FrameNE, C_FrameSW,
78 C_FrameSE},
79 {FR_N, FR_E, FR_S, FR_W, FR_NW, FR_NE, FR_SW, FR_SE},
80 /* N E S W NW NE SW SE TITLE */
81 {FR_N, FR_E, FR_S, FR_W, FR_N, FR_N, FR_S, FR_S, FR_N},
82 FR_N,
83 {FR_NW, FR_NE},
84 {FR_NW, FR_NE},
85 FR_S,
86 {FR_SW, FR_SE},
87 {FR_SW, FR_SE},
88 FR_W, FR_E,
89 FR_W, FR_E,
90 MYFRAME_HOR_MASK,
91 TBTN_ORDER_L2R, TBTN_ORDER_L2R,
92 &NormalX, &NormalY, &NormalWidth, &NormalHeight,
93 &NormalX, &NormalY, &NormalWidth, &NormalHeight,
94 0,
95 {0, 1, 2, 3, 4, 5, 6},
96 {0, 0, 0, 0, 0, 0, 0}
97 };
98
99 ASOrientation VertOrientation = {
100 {C_FrameW, C_FrameN, C_FrameE, C_FrameS, C_FrameSW, C_FrameNW, C_FrameSE,
101 C_FrameNE},
102 {FR_W, FR_N, FR_E, FR_S, FR_SW, FR_NW, FR_SE, FR_NE},
103 /* N E S W NW NE SW SE TITLE */
104 {FR_N, FR_E, FR_S, FR_W, FR_W, FR_E, FR_W, FR_E, FR_W},
105 FR_W,
106 {FR_SW, FR_NW},
107 {FR_NW, FR_SW},
108 FR_E,
109 {FR_SE, FR_NE},
110 {FR_NE, FR_SE},
111 FR_S, FR_N,
112 FR_N, FR_S,
113 MYFRAME_VERT_MASK,
114 TBTN_ORDER_B2T, TBTN_ORDER_B2T,
115 &NormalX, &NormalY, &NormalWidth, &NormalHeight,
116 &NormalY, &NormalX, &NormalHeight, &NormalWidth,
117 FLIP_VERTICAL,
118 {0, 0, 0, 0, 0, 0, 0},
119 {7, 6, 5, 4, 3, 2, 1}
120 };
121
get_orientation_data(ASWindow * asw)122 ASOrientation *get_orientation_data (ASWindow * asw)
123 {
124 if (asw && asw->magic == MAGIC_ASWINDOW && asw->hints)
125 return ASWIN_HFLAGS (asw,
126 AS_VerticalTitle) ? &VertOrientation :
127 &HorzOrientation;
128 return &HorzOrientation;
129 }
130
131 void
compile_tbar_layout(unsigned int * tbar_layout,unsigned int * default_tbar_layout,unsigned long left_layout,unsigned long right_layout)132 compile_tbar_layout (unsigned int *tbar_layout,
133 unsigned int *default_tbar_layout,
134 unsigned long left_layout, unsigned long right_layout)
135 {
136 int l, r;
137
138 Bool used[MYFRAME_TITLE_BACKS] =
139 { False, False, False, False, False, False, False };
140
141 LOCAL_DEBUG_OUT ("left_layout = %lX, right_layout = %lX", left_layout,
142 right_layout);
143 for (l = 0; l < MYFRAME_TITLE_BACKS; ++l)
144 tbar_layout[l] = -1;
145 for (l = 0; l < MYFRAME_TITLE_SIDE_ELEMS; ++l) {
146 int elem = MYFRAME_GetTbarLayoutElem (left_layout, l);
147
148 if (elem != MYFRAME_TITLE_BACK_INVALID && !used[l]) {
149 tbar_layout[elem] = default_tbar_layout[l];
150 used[l] = True;
151 }
152 }
153 for (r = MYFRAME_TITLE_BACKS; r > MYFRAME_TITLE_SIDE_ELEMS + 1;) {
154 int elem =
155 MYFRAME_GetTbarLayoutElem (right_layout,
156 (MYFRAME_TITLE_BACKS - r));
157 --r;
158 LOCAL_DEBUG_OUT ("r = %d, elem = %d, used = %d", r, elem, used[r]);
159 if (elem != MYFRAME_TITLE_BACK_INVALID && !used[r]) {
160 /* right layout is in reverse order ! */
161 elem = MYFRAME_TITLE_BACKS - MYFRAME_TITLE_SIDE_ELEMS + elem;
162 tbar_layout[elem] = default_tbar_layout[r];
163 LOCAL_DEBUG_OUT ("right_elem %d has slot = %d", elem,
164 tbar_layout[elem]);
165 used[r] = True;
166 }
167 }
168
169 tbar_layout[MYFRAME_TITLE_BACK_LBL] =
170 default_tbar_layout[MYFRAME_TITLE_BACK_LBL];
171 used[MYFRAME_TITLE_BACK_LBL] = True;
172 for (l = 0; l < MYFRAME_TITLE_BACKS; ++l) {
173 if (tbar_layout[l] == -1) {
174 int i;
175 int from = 0, to = MYFRAME_TITLE_SIDE_ELEMS;
176 if (l >= MYFRAME_TITLE_SIDE_ELEMS) {
177 from = MYFRAME_TITLE_BACK_LEFT2RIGHT (MYFRAME_TITLE_SIDE_ELEMS);
178 to = MYFRAME_TITLE_BACKS;
179 }
180 LOCAL_DEBUG_OUT ("missing layout for elem %d, from = %d, to = %d", l,
181 from, to);
182 for (i = from; i < to; ++i) {
183 if (!used[i]) {
184 LOCAL_DEBUG_OUT ("found vacant slot %d", default_tbar_layout[i]);
185 tbar_layout[l] = default_tbar_layout[i];
186 used[i] = True;
187 break;
188 }
189 }
190 }
191 }
192 }
193
194 /* this gets called when Look changes or hints changes : */
check_side_canvas(ASWindow * asw,FrameSide side,Bool required)195 static ASCanvas *check_side_canvas (ASWindow * asw, FrameSide side,
196 Bool required)
197 {
198 ASCanvas *canvas = asw->frame_sides[side];
199 Window w;
200 LOCAL_DEBUG_CALLER_OUT ("asw = %p, side = %d, required = %d", asw, side,
201 required);
202 if (required) {
203 if (canvas == NULL) { /* create canvas here */
204 unsigned long valuemask;
205 XSetWindowAttributes attributes;
206
207 valuemask = CWBorderPixel | CWEventMask;
208 attributes.border_pixel = Scr.asv->black_pixel;
209 if (Scr.Feel.flags & BackingStore) {
210 valuemask |= CWBackingStore;
211 attributes.backing_store = WhenMapped;
212 }
213 attributes.event_mask = AS_CANVAS_EVENT_MASK;
214
215 w = create_visual_window (Scr.asv, asw->frame,
216 0, 0, 1, 1, 0, InputOutput,
217 valuemask, &attributes);
218 register_aswindow (w, asw);
219 canvas = create_ascanvas (w);
220 LOCAL_DEBUG_OUT
221 ("++CREAT Client(%lx(%s))->side(%d)->canvas(%p)->window(%lx)",
222 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", side,
223 canvas, canvas->w);
224 } else
225 invalidate_canvas_config (canvas);
226 } else if (canvas != NULL) { /* destroy canvas here */
227 w = canvas->w;
228 LOCAL_DEBUG_OUT
229 ("--DESTR Client(%lx(%s))->side(%d)->canvas(%p)->window(%lx)",
230 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", side,
231 canvas, canvas->w);
232 destroy_ascanvas (&canvas);
233 destroy_registered_window (w);
234 }
235
236 return (asw->frame_sides[side] = canvas);
237 }
238
239 /* creating/destroying our main frame window : */
check_frame_canvas(ASWindow * asw,Bool required)240 static ASCanvas *check_frame_canvas (ASWindow * asw, Bool required)
241 {
242 ASCanvas *canvas = asw->frame_canvas;
243 Window w;
244
245 if (required) {
246 if (canvas == NULL) { /* create canvas here */
247 unsigned long valuemask;
248 XSetWindowAttributes attributes;
249 int bw = 0;
250
251 /* create windows */
252 valuemask = CWBorderPixel | CWCursor | CWEventMask;
253 if (Scr.asv->visual_info.visual == DefaultVisual (dpy, Scr.screen)) {
254 /* only if root has same depth and visual as us! */
255 attributes.background_pixmap = ParentRelative;
256 valuemask |= CWBackPixmap;
257 }
258 attributes.border_pixel = Scr.asv->black_pixel;
259 attributes.cursor = Scr.Feel.cursors[ASCUR_Default];
260 attributes.event_mask = AS_FRAME_EVENT_MASK;
261
262 if (get_flags (Scr.Feel.flags, SaveUnders)) {
263 valuemask |= CWSaveUnder;
264 attributes.save_under = True;
265 }
266 if (asw->hints && get_flags (asw->hints->flags, AS_Border))
267 bw = asw->hints->border_width;
268 asw->status->frame_border_width = bw;
269 w = create_visual_window (Scr.asv,
270 (ASWIN_DESK (asw) ==
271 Scr.CurrentDesk) ? Scr.Root : Scr.
272 ServiceWin, asw->status->x, asw->status->y,
273 asw->status->width, asw->status->height,
274 bw, InputOutput, valuemask, &attributes);
275 XLowerWindow (dpy, w);
276 asw->frame = w;
277 register_aswindow (w, asw);
278 canvas = create_ascanvas_container (w);
279 LOCAL_DEBUG_OUT
280 ("++CREAT Client(%lx(%s))->FRAME->canvas(%p)->window(%lx)->parent(%lx)",
281 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
282 canvas->w,
283 (ASWIN_DESK (asw) ==
284 Scr.CurrentDesk) ? Scr.Root : Scr.ServiceWin);
285 } else
286 invalidate_canvas_config (canvas);
287 } else if (canvas != NULL) { /* destroy canvas here */
288 w = canvas->w;
289 LOCAL_DEBUG_OUT
290 ("--DESTR Client(%lx(%s))->FRAME->canvas(%p)->window(%lx)", asw->w,
291 ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
292 canvas->w);
293 destroy_ascanvas (&canvas);
294 destroy_registered_window (w);
295 }
296
297 return (asw->frame_canvas = canvas);
298 }
299
300 /* creating/destroying container canvas for our client's window : */
check_client_canvas(ASWindow * asw,Bool required)301 static ASCanvas *check_client_canvas (ASWindow * asw, Bool required)
302 {
303 ASCanvas *canvas = asw->client_canvas;
304 Window w;
305
306 if (required) {
307 if (canvas == NULL) { /* create canvas here */
308 unsigned long valuemask;
309 XSetWindowAttributes attributes;
310
311 if (asw->frame == None || (w = asw->w) == None)
312 return NULL;
313
314 attributes.event_mask = AS_CLIENT_EVENT_MASK;
315 if (asw->internal) {
316 XWindowAttributes internal_attr;
317 XGetWindowAttributes (dpy, w, &internal_attr);
318 attributes.event_mask |= internal_attr.your_event_mask;
319 }
320 quietly_reparent_window (w, asw->frame, 0, 0, attributes.event_mask);
321
322 valuemask = (CWEventMask | CWDontPropagate);
323 attributes.do_not_propagate_mask =
324 ButtonPressMask | ButtonReleaseMask;
325
326 if (get_flags (Scr.Feel.flags, AppsBackingStore)) {
327 valuemask |= CWBackingStore;
328 attributes.backing_store = WhenMapped;
329 }
330 XChangeWindowAttributes (dpy, w, valuemask, &attributes);
331 if (asw->internal == NULL)
332 XAddToSaveSet (dpy, w);
333
334 register_aswindow (w, asw);
335 canvas = create_ascanvas_container (w);
336 if (ASWIN_GET_FLAGS (asw, AS_Shaped))
337 refresh_container_shape (canvas);
338 LOCAL_DEBUG_OUT
339 ("++CREAT Client(%lx(%s))->CLIENT->canvas(%p)->window(%lx)",
340 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
341 canvas->w);
342 }
343 /*else invalidate_canvas_config( canvas ); */
344 } else if (canvas != NULL) { /* destroy canvas here */
345 XWindowChanges xwc; /* our withdrawn geometry */
346 ASStatusHints withdrawn_status = { 0 };
347 register int i = 0;
348
349 w = canvas->w;
350
351 /* calculating the withdrawn location */
352 if (asw->status)
353 withdrawn_status = *(asw->status);
354
355 xwc.border_width = withdrawn_status.border_width;
356
357 for (i = 0; i < FRAME_SIDES; ++i)
358 withdrawn_status.frame_size[i] = 0;
359 clear_flags (withdrawn_status.flags, AS_Shaded | AS_Iconic);
360 anchor2status (&withdrawn_status, asw->hints, &(asw->anchor));
361 xwc.x = withdrawn_status.x;
362 xwc.y = withdrawn_status.y;
363 xwc.width = withdrawn_status.width;
364 xwc.height = withdrawn_status.height;
365
366 LOCAL_DEBUG_OUT
367 ("--DESTR Client(%lx(%s))->CLIENT->canvas(%p)->window(%lx)",
368 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
369 canvas->w);
370 destroy_ascanvas (&canvas);
371
372 /*
373 * Prevent the receipt of an UnmapNotify in case we are simply restarting,
374 * since that would cause a transition to the Withdrawn state.
375 */
376 #if 1
377 if ((asw->status == NULL || !get_flags (asw->status->flags, AS_Dead))
378 && get_parent_window (w) == asw->frame) {
379 LOCAL_DEBUG_OUT ("reparenting client window %lX", w);
380 if (get_flags (AfterStepState, ASS_Shutdown))
381 quietly_reparent_window (w, Scr.Root, xwc.x, xwc.y,
382 AS_CLIENT_EVENT_MASK);
383 else
384 XReparentWindow (dpy, w, Scr.Root, xwc.x, xwc.y);
385 /* WE have to restore window's withdrawn location now. */
386 XConfigureWindow (dpy, w,
387 CWX | CWY | CWWidth | CWHeight | CWBorderWidth,
388 &xwc);
389 }
390 XSync (dpy, 0);
391 #endif
392 }
393
394 asw->client_canvas = canvas;
395 return canvas;
396 }
397
398 /* creating/destroying our icon window : */
check_icon_canvas(ASWindow * asw,Bool required)399 static ASCanvas *check_icon_canvas (ASWindow * asw, Bool required)
400 {
401 ASCanvas *canvas = asw->icon_canvas;
402 Window w;
403
404 if (required) {
405 if (canvas == NULL) { /* create canvas here */
406 unsigned long valuemask;
407 XSetWindowAttributes attributes;
408
409 valuemask = CWBorderPixel | CWCursor | CWEventMask;
410 attributes.border_pixel = Scr.asv->black_pixel;
411 attributes.cursor = Scr.Feel.cursors[ASCUR_Default];
412
413 if ((get_flags (asw->hints->client_icon_flags, AS_ClientIcon | AS_ClientIconPixmap) != AS_ClientIcon) || asw->hints == NULL || asw->hints->icon.window == None || !get_flags (Scr.Feel.flags, KeepIconWindows)) { /* create windows */
414 attributes.event_mask = AS_ICON_TITLE_EVENT_MASK;
415 w = create_visual_window (Scr.asv,
416 (ASWIN_DESK (asw) ==
417 Scr.CurrentDesk) ? Scr.Root : Scr.
418 ServiceWin, -9000, -9000, 1, 1, 0,
419 InputOutput, valuemask, &attributes);
420 canvas = create_ascanvas (w);
421 } else { /* reuse client's provided window */
422 attributes.event_mask = AS_ICON_EVENT_MASK;
423 w = asw->hints->icon.window;
424 XChangeWindowAttributes (dpy, w, valuemask, &attributes);
425 canvas = create_ascanvas_container (w);
426 }
427 LOCAL_DEBUG_OUT
428 ("++CREAT Client(%lx(%s))->ICON->canvas(%p)->window(%lx)",
429 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
430 canvas->w);
431 register_aswindow (w, asw);
432 } else
433 invalidate_canvas_config (canvas);
434 } else if (canvas != NULL) { /* destroy canvas here */
435 w = canvas->w;
436 LOCAL_DEBUG_OUT
437 ("--DESTR Client(%lx(%s))->ICON->canvas(%p)->window(%lx)", asw->w,
438 ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
439 canvas->w);
440 if (asw->icon_title_canvas == canvas)
441 asw->icon_title_canvas = NULL;
442 destroy_ascanvas (&canvas);
443 if (asw->hints && asw->hints->icon.window == w)
444 unregister_aswindow (w);
445 else
446 destroy_registered_window (w);
447 }
448 asw->icon_canvas = canvas;
449
450 return canvas;
451 }
452
453 /* creating/destroying our icon title window : */
check_icon_title_canvas(ASWindow * asw,Bool required,Bool reuse_icon_canvas)454 static ASCanvas *check_icon_title_canvas (ASWindow * asw, Bool required,
455 Bool reuse_icon_canvas)
456 {
457 ASCanvas *canvas = asw->icon_title_canvas;
458 Window w;
459
460 if (!required) {
461 if (canvas && canvas != asw->icon_canvas) {
462 w = canvas->w;
463 LOCAL_DEBUG_OUT
464 ("--DESTR Client(%lx(%s))->ICONT->canvas(%p)->window(%lx)",
465 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
466 canvas->w);
467 destroy_ascanvas (&canvas);
468 destroy_registered_window (w);
469 }
470 } else { /* if( required ) */
471
472 if (reuse_icon_canvas)
473 canvas = asw->icon_canvas;
474 else if (canvas == NULL) { /* create canvas here */
475 unsigned long valuemask;
476 XSetWindowAttributes attributes;
477
478 valuemask = CWBorderPixel | CWCursor | CWEventMask;
479 attributes.border_pixel = Scr.asv->black_pixel;
480 attributes.cursor = Scr.Feel.cursors[ASCUR_Default];
481 attributes.event_mask = AS_ICON_TITLE_EVENT_MASK;
482 /* create windows */
483 w = create_visual_window (Scr.asv,
484 (ASWIN_DESK (asw) ==
485 Scr.CurrentDesk) ? Scr.Root : Scr.
486 ServiceWin, -9010, -9010, 1, 1, 0,
487 InputOutput, valuemask, &attributes);
488
489 register_aswindow (w, asw);
490 canvas = create_ascanvas (w);
491 LOCAL_DEBUG_OUT
492 ("++CREAT Client(%lx(%s))->ICONT->canvas(%p)->window(%lx)",
493 asw->w, ASWIN_NAME (asw) ? ASWIN_NAME (asw) : "noname", canvas,
494 canvas->w);
495 } else
496 invalidate_canvas_config (canvas);
497 }
498
499 asw->icon_title_canvas = canvas;
500
501 return canvas;
502 }
503
504 /* pointers should point to valid values preset to 0, im.width, 0, im.height */
505 static void
geometry2slicing(ASGeometry g,int * pxs,int * pxe,int * pys,int * pye)506 geometry2slicing (ASGeometry g, int *pxs, int *pxe, int *pys, int *pye)
507 {
508 if (get_flags (g.flags, XValue))
509 *pxs = get_flags (g.flags, XNegative) ? *pxe + g.x : g.x;
510 if (get_flags (g.flags, YValue))
511 *pys = get_flags (g.flags, YNegative) ? *pye + g.y : g.y;
512
513 if (get_flags (g.flags, WidthValue))
514 *pxe = *pxs + g.width;
515 if (get_flags (g.flags, HeightValue))
516 *pye = *pys + g.height;
517 }
518
519
check_tbar(ASTBarData ** tbar,Bool required,const char * mystyle_name,ASImage * img,unsigned short back_w,unsigned short back_h,int flip,ASFlagType align,ASFlagType fbevel,ASFlagType ubevel,unsigned char fcm,unsigned char ucm,int context,ASGeometry * slicing)520 static ASTBarData *check_tbar (ASTBarData ** tbar, Bool required,
521 const char *mystyle_name, ASImage * img,
522 unsigned short back_w,
523 unsigned short back_h, int flip,
524 ASFlagType align, ASFlagType fbevel,
525 ASFlagType ubevel, unsigned char fcm,
526 unsigned char ucm, int context,
527 ASGeometry * slicing)
528 {
529 if (required) {
530 if (*tbar == NULL) {
531 *tbar = create_astbar ();
532 LOCAL_DEBUG_OUT ("++CREAT tbar(%p)->context(%s)", *tbar,
533 context2text (context));
534 } else
535 delete_astbar_tile (*tbar, -1);
536
537 set_astbar_flip (*tbar, flip);
538
539 invalidate_astbar_style (*tbar, -1);
540 set_astbar_style (*tbar, BAR_STATE_FOCUSED, mystyle_name);
541 set_astbar_style (*tbar, BAR_STATE_UNFOCUSED, "default");
542 if (img) {
543 LOCAL_DEBUG_OUT ("adding bar icon %p %ux%u", img, img->width,
544 img->height);
545 if (slicing && slicing->flags) {
546 int xs = 0, xe = 0, ys = img->width, ye = img->height;
547 geometry2slicing (*slicing, &xs, &xe, &ys, &ye);
548 add_astbar_image (*tbar, 0, 0, flip, align, img, xs, xe, ys, ye);
549 } else
550 add_astbar_icon (*tbar, 0, 0, flip, align, img);
551 if (back_w == 0)
552 back_w =
553 get_flags (flip, FLIP_VERTICAL) ? img->height : img->width;
554 if (back_h == 0)
555 back_h =
556 get_flags (flip, FLIP_VERTICAL) ? img->width : img->height;
557 }
558
559 set_astbar_hilite (*tbar, BAR_STATE_FOCUSED, fbevel);
560 set_astbar_hilite (*tbar, BAR_STATE_UNFOCUSED, ubevel);
561 set_astbar_composition_method (*tbar, BAR_STATE_FOCUSED, fcm);
562 set_astbar_composition_method (*tbar, BAR_STATE_UNFOCUSED, ucm);
563 set_astbar_size (*tbar, (back_w == 0) ? 1 : back_w,
564 (back_h == 0) ? 1 : back_h);
565 (*tbar)->context = context;
566 } else if (*tbar) {
567 destroy_astbar (tbar);
568 }
569 return *tbar;
570 }
571
572 /******************************************************************************/
573 /* now externally available interfaces to the above functions : */
574 /******************************************************************************/
invalidate_window_icon(ASWindow * asw)575 void invalidate_window_icon (ASWindow * asw)
576 {
577 if (asw)
578 check_icon_canvas (asw, False);
579 }
580
invalidate_window_mystyles(ASWindow * asw)581 void invalidate_window_mystyles (ASWindow * asw)
582 {
583 int i;
584
585 for (i = 0; i < FRAME_PARTS; ++i)
586 if (asw->frame_bars[i])
587 invalidate_astbar_style (asw->frame_bars[i], -1);
588 if (asw->tbar)
589 invalidate_astbar_style (asw->tbar, -1);
590 if (asw->icon_button)
591 invalidate_astbar_style (asw->icon_button, -1);
592 if (asw->icon_title)
593 invalidate_astbar_style (asw->icon_title, -1);
594 }
595
596 /***********************************************************************
597 * grab_aswindow_buttons - grab needed buttons for all of the windows
598 * for specified client
599 ***********************************************************************/
grab_aswindow_buttons(ASWindow * asw,Bool focused)600 void grab_aswindow_buttons (ASWindow * asw, Bool focused)
601 {
602 if (asw) {
603 Bool do_focus_grab = (get_flags (Scr.Feel.flags, ClickToFocus));
604 if (do_focus_grab) {
605 if (focused)
606 ungrab_focus_click (asw->frame);
607 else
608 grab_focus_click (asw->frame);
609 } else
610 ungrab_window_buttons (asw->frame);
611
612 if (!ASWIN_GET_FLAGS (asw, AS_Dead)) {
613 ungrab_window_buttons (asw->w);
614 grab_window_buttons (asw->w, C_WINDOW);
615 }
616
617 if (asw->icon_canvas && !ASWIN_GET_FLAGS (asw, AS_Dead)
618 && validate_drawable (asw->icon_canvas->w, NULL, NULL) != None) {
619 ungrab_window_buttons (asw->icon_canvas->w);
620 if (do_focus_grab) {
621 if (focused)
622 ungrab_focus_click (asw->icon_canvas->w);
623 else
624 grab_focus_click (asw->icon_canvas->w);
625 }
626 grab_window_buttons (asw->icon_canvas->w, C_ICON);
627 }
628
629 if (asw->icon_title_canvas
630 && asw->icon_title_canvas != asw->icon_canvas) {
631 ungrab_window_buttons (asw->icon_title_canvas->w);
632 if (do_focus_grab) {
633 if (focused)
634 ungrab_focus_click (asw->icon_title_canvas->w);
635 else
636 grab_focus_click (asw->icon_title_canvas->w);
637 }
638 grab_window_buttons (asw->icon_title_canvas->w, C_ICON);
639
640 }
641 }
642 XSync (dpy, False);
643 }
644
645 /***********************************************************************
646 * grab_aswindow_keys - grab needed keys for the window
647 ***********************************************************************/
grab_aswindow_keys(ASWindow * asw)648 void grab_aswindow_keys (ASWindow * asw)
649 {
650 if (AS_ASSERT (asw))
651 return;
652
653 ungrab_window_keys (asw->frame);
654 grab_window_keys (asw->frame,
655 (C_WINDOW | C_TITLE | C_TButtonAll | C_FRAME));
656
657 if (asw->icon_canvas) {
658 ungrab_window_keys (asw->icon_canvas->w);
659 grab_window_keys (asw->icon_canvas->w, (C_ICON));
660 }
661 if (asw->icon_title_canvas && asw->icon_title_canvas != asw->icon_canvas) {
662 ungrab_window_keys (asw->icon_title_canvas->w);
663 grab_window_keys (asw->icon_title_canvas->w, (C_ICON));
664 }
665 XSync (dpy, False);
666 }
667
668
669 /* this should set up proper feel settings - grab keyboard and mouse buttons :
670 * Note: must be called after redecorate_window, since some of windows may have
671 * been created at that time.
672 */
grab_window_input(ASWindow * asw,Bool release_grab)673 void grab_window_input (ASWindow * asw, Bool release_grab)
674 {
675 if (asw) {
676 if (release_grab) {
677 ungrab_window_keys (asw->frame);
678 ungrab_window_buttons (asw->frame);
679 if (asw->icon_canvas) {
680 ungrab_window_keys (asw->icon_canvas->w);
681 ungrab_window_buttons (asw->icon_canvas->w);
682 }
683 if (asw->icon_title_canvas
684 && asw->icon_title_canvas != asw->icon_canvas) {
685 ungrab_window_keys (asw->icon_title_canvas->w);
686 ungrab_window_buttons (asw->icon_title_canvas->w);
687 }
688 XSync (dpy, False);
689 } else {
690 grab_aswindow_buttons (asw, (Scr.Windows->focused == asw));
691 grab_aswindow_keys (asw);
692 }
693 }
694 }
695
696 /*
697 ** returns a newline delimited list of the Mouse functions bound to a
698 ** given context, in human readable form
699 */
list_functions_by_context(int context,ASHints * hints)700 char *list_functions_by_context (int context, ASHints * hints)
701 {
702 MouseButton *btn;
703 char *str = NULL;
704 int allocated_bytes = 0;
705 if (hints == NULL)
706 return NULL;
707 for (btn = Scr.Feel.MouseButtonRoot; btn != NULL; btn = btn->NextButton)
708 if ((btn->Context & context)
709 && check_allowed_function (btn->fdata, hints)) {
710 TermDef *fterm;
711
712 fterm = func2fterm (btn->fdata->func, True);
713 if (fterm != NULL) {
714 char *ptr;
715
716 if (str) {
717 str =
718 realloc (str, allocated_bytes + 1 + fterm->keyword_len + 32);
719 ptr = str + allocated_bytes;
720 *(ptr++) = '\n';
721 } else
722 ptr = str = safemalloc (fterm->keyword_len + 32);
723
724 sprintf (ptr, "%s: ", fterm->keyword);
725 ptr += fterm->keyword_len + 2;
726 if (btn->Modifier & ShiftMask) {
727 strcat (ptr, "Shift+");
728 ptr += 8;
729 }
730 if (btn->Modifier & ControlMask) {
731 strcat (ptr, "Ctrl+");
732 ptr += 7;
733 }
734 if (btn->Modifier & Mod1Mask) {
735 strcat (ptr, "Meta+");
736 ptr += 7;
737 }
738 sprintf (ptr, "Button %d", btn->Button);
739 allocated_bytes = strlen (str);
740 }
741 }
742 return str;
743 }
744
745
746
747 /****************************************************************************
748 *
749 * Checks the function "function", and sees if it
750 * is an allowed function for window t, according to the motif way of life.
751 * This routine is used to decide if we should refuse to perform a function.
752 *
753 ****************************************************************************/
check_allowed_function2(int func,ASHints * hints)754 int check_allowed_function2 (int func, ASHints * hints)
755 {
756 if (func == F_NOP)
757 return 0;
758
759 if (hints) {
760 int mask = function2mask (func);
761 if (func == F_SHADE)
762 return get_flags (hints->flags, AS_Titlebar);
763 else if (mask != 0)
764 return get_flags (hints->function_mask, mask);
765 }
766 return 1;
767 }
768
769 /****************************************************************************
770 *
771 * Checks the function described in menuItem mi, and sees if it
772 * is an allowed function for window Tmp_Win,
773 * according to the motif way of life.
774 *
775 * This routine is used to determine whether or not to grey out menu items.
776 *
777 ****************************************************************************/
check_allowed_function(FunctionData * fdata,ASHints * hints)778 int check_allowed_function (FunctionData * fdata, ASHints * hints)
779 {
780 int func = fdata->func;
781 int i;
782 ComplexFunction *cfunc;
783
784 if (func != F_FUNCTION && func != F_CATEGORY)
785 return check_allowed_function2 (func, hints);
786
787 if (func == F_FUNCTION) {
788 if ((cfunc = get_complex_function (fdata->name)) == NULL)
789 return 0;
790
791 for (i = 0; i < cfunc->items_num; ++i)
792 if (cfunc->items[i].func == F_FUNCTION
793 || cfunc->items[i].func == F_CATEGORY) {
794 if (check_allowed_function (&(cfunc->items[i]), hints) == 0)
795 return 0;
796 } else if (check_allowed_function2 (cfunc->items[i].func, hints) ==
797 0)
798 return 0;
799 } else if (func == F_CATEGORY) {
800 if (name2desktop_category
801 (fdata->text ? fdata->text : fdata->name, NULL) == NULL)
802 return 0;
803 }
804 return 1;
805 }
806
807
compile_titlebuttons_mask(ASHints * hints)808 ASFlagType compile_titlebuttons_mask (ASHints * hints)
809 {
810 ASFlagType disabled_mask = hints->disabled_buttons;
811 ASFlagType enabled_mask = 0;
812 int i;
813
814 LOCAL_DEBUG_OUT ("disabled mask from hints is 0x%lX", disabled_mask);
815
816 for (i = 0; i < TITLE_BUTTONS; i++) {
817 if (Scr.Look.buttons[i].unpressed.image != NULL) {
818 int context = Scr.Look.buttons[i].context;
819 MouseButton *func;
820 Bool at_least_one_enabled = False;
821
822 enabled_mask |= context;
823 for (func = Scr.Feel.MouseButtonRoot; func != NULL;
824 func = (*func).NextButton)
825 if ((func->Context & context) != 0)
826 if (check_allowed_function (func->fdata, hints)) {
827 at_least_one_enabled = True;
828 break;
829 }
830 if (!at_least_one_enabled)
831 disabled_mask |= Scr.Look.buttons[i].context;
832 }
833 }
834 LOCAL_DEBUG_OUT
835 ("disabled mask(0x%lX)->enabled_mask(0x%lX)->button_mask(0x%lX)",
836 disabled_mask, enabled_mask, enabled_mask & (~disabled_mask));
837
838
839 return enabled_mask & (~disabled_mask);
840 }
841
842 void
estimate_titlebar_size(ASHints * hints,unsigned int * width_ret,unsigned int * height_ret)843 estimate_titlebar_size (ASHints * hints, unsigned int *width_ret,
844 unsigned int *height_ret)
845 {
846 unsigned int width = 0, height = 0;
847 if (hints) {
848 ASTBarData *tbar = create_astbar ();
849 ASFlagType btn_mask;
850
851 btn_mask = compile_titlebuttons_mask (hints);
852 tbar->h_spacing = DEFAULT_TBAR_HSPACING;
853 tbar->v_spacing = DEFAULT_TBAR_VSPACING;
854 /* left buttons : */
855 add_astbar_btnblock (tbar, 0, 0, 0, NO_ALIGN,
856 &(Scr.Look.ordered_buttons[0]), btn_mask,
857 Scr.Look.button_first_right,
858 Scr.Look.TitleButtonXOffset[0],
859 Scr.Look.TitleButtonYOffset[0],
860 Scr.Look.TitleButtonSpacing[0], TBTN_ORDER_L2R);
861
862 /* label */
863 add_astbar_label (tbar, 1, 0, 0, ALIGN_LEFT, DEFAULT_TBAR_HSPACING,
864 DEFAULT_TBAR_VSPACING, hints->names[0],
865 hints->names_encoding[0]);
866 /* right buttons : */
867 add_astbar_btnblock (tbar, 2, 0, 0, NO_ALIGN,
868 &(Scr.Look.
869 ordered_buttons[Scr.Look.button_first_right]),
870 btn_mask,
871 TITLE_BUTTONS - Scr.Look.button_first_right,
872 Scr.Look.TitleButtonXOffset[1],
873 Scr.Look.TitleButtonYOffset[1],
874 Scr.Look.TitleButtonSpacing[1], TBTN_ORDER_R2L);
875
876 set_astbar_style_ptr (tbar, BAR_STATE_UNFOCUSED,
877 Scr.Look.MSMenu[MENU_BACK_TITLE]);
878 set_astbar_style_ptr (tbar, BAR_STATE_FOCUSED,
879 Scr.Look.MSMenu[MENU_BACK_HITITLE]);
880 width = calculate_astbar_width (tbar);
881 height = calculate_astbar_height (tbar);
882 destroy_astbar (&tbar);
883 }
884 if (width_ret)
885 *width_ret = width;
886 if (height_ret)
887 *height_ret = height;
888 }
889
fix_background_align(ASFlagType align)890 inline static ASFlagType fix_background_align (ASFlagType align)
891 {
892 ASFlagType new_align = align;
893 /* don't ask why - simply magic :)
894 * Well not really - we want to disregard background size in calculations of overall
895 * titlebar size. Overall titlebar size is determined only by text size and button sizes.
896 * At the same time we would like to be able to scale backgrounds to the size of the
897 * titlebar
898 */
899 /* clear_flags(new_align , (RESIZE_H|RESIZE_V)); */
900 if (get_flags (new_align, RESIZE_H_SCALE))
901 set_flags (new_align, FIT_LABEL_WIDTH);
902 if (get_flags (new_align, RESIZE_V_SCALE))
903 set_flags (new_align, FIT_LABEL_HEIGHT);
904 LOCAL_DEBUG_OUT ("Fixed align from 0x%lx to 0x%lx", align, new_align);
905 return new_align;
906 }
907
hints2decorations(ASWindow * asw,ASHints * old_hints)908 Bool hints2decorations (ASWindow * asw, ASHints * old_hints)
909 {
910 int i;
911 MyFrame *frame = NULL, *old_frame = NULL;
912 Bool has_tbar = False, had_tbar = False;
913 Bool icon_image_changed = True;
914 ASOrientation *od = get_orientation_data (asw);
915 char *mystyle_name = Scr.Look.MSWindow[BACK_FOCUSED]->name;
916 char *frame_mystyle_name = NULL;
917 unsigned int *frame_contexts = &(od->frame_contexts[0]);
918 Bool tbar_created = False;
919 Bool status_changed = False;
920
921 LOCAL_DEBUG_CALLER_OUT ("asw(%p)->client(%lX)", asw, asw ? asw->w : 0);
922
923 /* 3) we need to prepare icon window : */
924 check_icon_canvas (asw,
925 (ASWIN_HFLAGS (asw, AS_Icon)
926 && !get_flags (Scr.Feel.flags, SuppressIcons)));
927
928 /* 4) we need to prepare icon title window : */
929 LOCAL_DEBUG_CALLER_OUT ("checking icon title canvas(%p)",
930 asw->icon_title_canvas);
931 check_icon_title_canvas (asw,
932 (ASWIN_HFLAGS (asw, AS_IconTitle)
933 && get_flags (Scr.Feel.flags, IconTitle)
934 && !get_flags (Scr.Feel.flags, SuppressIcons)),
935 !get_flags (Scr.Look.flags, SeparateButtonTitle)
936 && (asw->icon_canvas != NULL));
937
938 has_tbar = (ASWIN_HFLAGS (asw, AS_Titlebar) != 0);
939 frame =
940 myframe_find (ASWIN_HFLAGS (asw, AS_Frame) ? asw->hints->
941 frame_name : NULL);
942 if (old_hints == NULL) {
943 had_tbar = !has_tbar;
944 old_frame = NULL;
945 } else {
946 had_tbar = (get_flags (old_hints->flags, AS_Titlebar) != 0);
947 old_frame =
948 myframe_find (get_flags (old_hints->flags, AS_Frame) ? old_hints->
949 frame_name : NULL);
950 }
951
952 asw->frame_data = frame;
953
954 /* 5) we need to prepare windows for 4 frame decoration sides : */
955 if (has_tbar != had_tbar || frame != old_frame) {
956 LOCAL_DEBUG_OUT ("has_tbar = %d, has_top_parts = %d, ", has_tbar,
957 myframe_has_parts (frame, FRAME_TOP_MASK));
958 check_side_canvas (asw, od->tbar_side, has_tbar
959 || myframe_has_parts (frame, FRAME_TOP_MASK));
960 }
961 if (!ASWIN_HFLAGS (asw, AS_Handles)) {
962 check_side_canvas (asw, od->sbar_side, False);
963 check_side_canvas (asw, od->left_side, False);
964 check_side_canvas (asw, od->right_side, False);
965 } else if (frame != old_frame
966 || (old_hints
967 && get_flags (old_hints->flags,
968 AS_Handles) != ASWIN_HFLAGS (asw,
969 AS_Handles))) {
970 check_side_canvas (asw, od->sbar_side,
971 myframe_has_parts (frame, FRAME_BTM_MASK));
972 check_side_canvas (asw, od->left_side,
973 myframe_has_parts (frame, FRAME_LEFT_MASK));
974 check_side_canvas (asw, od->right_side,
975 myframe_has_parts (frame, FRAME_RIGHT_MASK));
976 }
977
978 if (ASWIN_HFLAGS (asw, AS_Handles)
979 && get_flags (frame->flags, MYFRAME_NOBORDER)) {
980 XSetWindowBorderWidth (dpy, asw->frame, 0);
981 asw->status->frame_border_width = 0;
982 } else if (asw->hints && get_flags (asw->hints->flags, AS_Border)) {
983 XSetWindowBorderWidth (dpy, asw->frame, asw->hints->border_width);
984 asw->status->frame_border_width = asw->hints->border_width;
985 }
986
987 /* make sure all our decoration windows are mapped and in proper order: */
988 if (!ASWIN_GET_FLAGS (asw, AS_Dead))
989 XRaiseWindow (dpy, asw->w);
990
991 /* 6) now we have to create bar for icon - if it is not client's animated icon */
992 if (asw->icon_canvas) {
993 if (old_hints) {
994 icon_image_changed =
995 (get_flags
996 (asw->hints->client_icon_flags,
997 AS_ClientIcon | AS_ClientIconPixmap) !=
998 get_flags (old_hints->client_icon_flags,
999 AS_ClientIcon | AS_ClientIconPixmap));
1000 if (!icon_image_changed)
1001 icon_image_changed =
1002 (asw->hints->icon.pixmap != old_hints->icon.pixmap);
1003 if (!icon_image_changed)
1004 icon_image_changed =
1005 (mystrcmp (asw->hints->icon_file, old_hints->icon_file) != 0);
1006 }
1007
1008 if (icon_image_changed) {
1009 ASImage *icon_image = get_client_icon_image (ASDefaultScr, asw->hints, 128);
1010 check_tbar (&(asw->icon_button), (asw->icon_canvas != NULL), AS_ICON_MYSTYLE, icon_image, Scr.Look.ButtonWidth, Scr.Look.ButtonHeight, /* scaling icon image */
1011 0, Scr.Look.ButtonAlign,
1012 Scr.Look.ButtonBevel, Scr.Look.ButtonBevel,
1013 TEXTURE_TRANSPIXMAP_ALPHA, TEXTURE_TRANSPIXMAP_ALPHA,
1014 C_IconButton, False);
1015
1016 if (icon_image)
1017 safe_asimage_destroy (icon_image);
1018 }
1019 }
1020 if (asw->icon_button && old_hints == NULL) {
1021 set_astbar_style (asw->icon_button, BAR_STATE_UNFOCUSED,
1022 AS_ICON_MYSTYLE);
1023 set_astbar_style (asw->icon_button, BAR_STATE_FOCUSED,
1024 AS_ICON_MYSTYLE);
1025 asw->icon_button->h_border = asw->icon_button->v_border =
1026 Scr.Look.ButtonIconSpacing;
1027 }
1028
1029 /* 7) now we have to create bar for icon title (optional) */
1030 check_tbar (&(asw->icon_title),
1031 get_flags (Scr.Feel.flags, IconTitle)
1032 &&
1033 ((asw->icon_canvas != NULL
1034 && !get_flags (Scr.Look.flags, SeparateButtonTitle))
1035 || asw->icon_title_canvas != NULL), AS_ICON_TITLE_MYSTYLE,
1036 NULL, 0, 0, 0, ALIGN_CENTER, DEFAULT_TBAR_HILITE,
1037 DEFAULT_TBAR_HILITE, TEXTURE_TRANSPIXMAP_ALPHA,
1038 TEXTURE_TRANSPIXMAP_ALPHA, C_IconTitle, False);
1039
1040 if (asw->icon_title) {
1041 LOCAL_DEBUG_OUT ("setting icon label to %s", ASWIN_ICON_NAME (asw));
1042 add_astbar_label (asw->icon_title, 0, 0, 0, frame->title_align,
1043 DEFAULT_TBAR_HSPACING, DEFAULT_TBAR_VSPACING,
1044 ASWIN_ICON_NAME (asw), ASWIN_ICON_NAME_ENC (asw));
1045 set_astbar_style (asw->icon_title, BAR_STATE_FOCUSED,
1046 AS_ICON_TITLE_MYSTYLE);
1047 set_astbar_style (asw->icon_title, BAR_STATE_UNFOCUSED,
1048 AS_ICON_TITLE_UNFOCUS_MYSTYLE);
1049 }
1050
1051 if (asw->hints->mystyle_names[BACK_FOCUSED])
1052 mystyle_name = asw->hints->mystyle_names[BACK_FOCUSED];
1053 if (frame->title_style_names[BACK_FOCUSED])
1054 mystyle_name = frame->title_style_names[BACK_FOCUSED];
1055 frame_mystyle_name = frame->frame_style_names[BACK_FOCUSED];
1056
1057 /* 8) now we have to create actuall bars - for each frame element plus one for the titlebar */
1058 for (i = 0; i < FRAME_SIDES; ++i)
1059 clear_flags (asw->internal_flags,
1060 ASWF_FirstCornerFollowsTbarSize << i);
1061 if (old_hints == NULL
1062 || (get_flags (old_hints->flags, AS_Handles) !=
1063 ASWIN_HFLAGS (asw, AS_Handles)) || old_frame != frame) {
1064 status_changed = True;
1065 if (ASWIN_HFLAGS (asw, AS_Handles)) {
1066 for (i = 0; i < FRAME_PARTS; ++i) {
1067 ASImage *img = NULL;
1068 unsigned int real_part = od->frame_rotation[i];
1069 int part_width = frame->part_width[i];
1070 int part_length = frame->part_length[i];
1071
1072 img = frame->parts[i] ? frame->parts[i]->image : NULL;
1073
1074 if (img == NULL) {
1075 if (i < FRAME_SIDES) {
1076 if (part_width == 0)
1077 part_width = BOUNDARY_WIDTH;
1078 if (part_length == 0)
1079 part_length = 1;
1080
1081 } else {
1082 if (part_width == 0) {
1083 part_width = CORNER_WIDTH;
1084 set_flags (asw->internal_flags,
1085 ASWF_FirstCornerFollowsTbarSize << (i -
1086 FRAME_SIDES));
1087 }
1088 if (part_length == 0)
1089 part_length = BOUNDARY_WIDTH;
1090 }
1091 }
1092
1093 if ((0x01 << i) & MYFRAME_HOR_MASK) {
1094 *(od->in_width) = part_length;
1095 *(od->in_height) = part_width;
1096 } else {
1097 *(od->in_width) = part_width;
1098 *(od->in_height) = part_length;
1099 }
1100 LOCAL_DEBUG_OUT
1101 ("part(%d)->real_part(%d)->from_size(%ux%u)->in_size(%ux%u)->out_size(%ux%u)",
1102 i, real_part, frame->part_width[i], frame->part_length[i],
1103 *(od->in_width), *(od->in_height), *(od->out_width),
1104 *(od->out_height));
1105 check_tbar (&(asw->frame_bars[real_part]), IsFramePart (frame, i),
1106 frame_mystyle_name ? frame_mystyle_name : mystyle_name,
1107 img, *(od->out_width), *(od->out_height), od->flip,
1108 frame->part_align[i], frame->part_fbevel[i],
1109 frame->part_ubevel[i], TEXTURE_TRANSPIXMAP_ALPHA,
1110 TEXTURE_TRANSPIXMAP_ALPHA, frame_contexts[i],
1111 (i < FRAME_SIDES) ? &(frame->part_slicing[i]) : NULL);
1112 }
1113 } else
1114 for (i = 0; i < FRAME_PARTS; ++i)
1115 check_tbar (&(asw->frame_bars[i]), False, NULL, NULL, 0, 0, 0, 0,
1116 0, 0, 0, 0, C_NO_CONTEXT, NULL);
1117
1118 check_tbar (&(asw->tbar), has_tbar, mystyle_name, NULL, 0, 0,
1119 od->flip,
1120 frame->title_align,
1121 frame->title_fbevel, frame->title_ubevel,
1122 frame->title_fcm, frame->title_ucm, C_TITLE, NULL);
1123 if (asw->tbar) {
1124 int fhue = -1, fsat = -1, uhue = -1, usat = -1;
1125 if (get_flags (frame->set_title_attr, MYFRAME_TitleFHueSet))
1126 fhue = frame->title_fhue;
1127 if (get_flags (frame->set_title_attr, MYFRAME_TitleFSatSet))
1128 fsat = frame->title_fsat;
1129 if (get_flags (frame->set_title_attr, MYFRAME_TitleUHueSet))
1130 uhue = frame->title_fhue;
1131 if (get_flags (frame->set_title_attr, MYFRAME_TitleUSatSet))
1132 usat = frame->title_fsat;
1133
1134 set_astbar_huesat (asw->tbar, BAR_STATE_FOCUSED, fhue, fsat);
1135 set_astbar_huesat (asw->tbar, BAR_STATE_UNFOCUSED, uhue, usat);
1136 }
1137
1138 tbar_created = (asw->tbar != NULL);
1139 }
1140
1141 if (asw->tbar) { /* 9) now we have to setup titlebar buttons */
1142 ASFlagType title_align = frame->title_align;
1143 ASFlagType btn_mask = compile_titlebuttons_mask (asw->hints);
1144 #ifdef SHAPE
1145 if (get_flags (frame->condense_titlebar, ALIGN_LEFT | ALIGN_RIGHT))
1146 ASWIN_SET_FLAGS (asw, AS_ShapedDecor);
1147 #endif
1148
1149 if (old_hints == NULL ||
1150 get_flags (old_hints->flags,
1151 AS_VerticalTitle) != ASWIN_HFLAGS (asw,
1152 AS_VerticalTitle)) {
1153 set_astbar_flip (asw->tbar,
1154 ASWIN_HFLAGS (asw,
1155 AS_VerticalTitle) ? FLIP_VERTICAL :
1156 0);
1157 if (!tbar_created) {
1158 tbar_created = True;
1159 delete_astbar_tile (asw->tbar, -1);
1160 }
1161 }
1162 /* need to add some titlebuttons */
1163 /* Don't need to do this as we already have padding set for label
1164 * if( tbar_created )
1165 * {
1166 * asw->tbar->h_spacing = DEFAULT_TBAR_SPACING ;
1167 * asw->tbar->v_spacing = DEFAULT_TBAR_SPACING ;
1168 * }
1169 */
1170
1171 if (!tbar_created && old_hints != NULL) {
1172 ASFlagType old_btn_mask = compile_titlebuttons_mask (old_hints);
1173 if (old_btn_mask != btn_mask)
1174 tbar_created = True;
1175 else if (frame != old_frame)
1176 tbar_created = True;
1177 if (tbar_created)
1178 delete_astbar_tile (asw->tbar, -1);
1179 }
1180
1181 if (!tbar_created) {
1182 if (old_hints == NULL ||
1183 mystrcmp (asw->hints->names[0], old_hints->names[0]) != 0) {
1184 ASCanvas *canvas =
1185 ASWIN_HFLAGS (asw,
1186 AS_VerticalTitle) ? asw->
1187 frame_sides[FR_W] : asw->frame_sides[FR_N];
1188 /* label ( goes on top of above pixmap ) */
1189 if (change_astbar_first_label
1190 (asw->tbar, ASWIN_NAME (asw), ASWIN_NAME_ENCODING (asw)))
1191 if (canvas) {
1192 render_astbar (asw->tbar, canvas);
1193 invalidate_canvas_save (canvas);
1194 update_canvas_display (canvas);
1195 }
1196 }
1197 } else {
1198 Bool rtitle_spacer_added = False;
1199 Bool ltitle_spacer_added = False;
1200 unsigned int tbar_layout_row[MYFRAME_TITLE_BACKS];
1201 unsigned int tbar_layout_col[MYFRAME_TITLE_BACKS];
1202
1203 compile_tbar_layout (tbar_layout_row, od->default_tbar_elem_row,
1204 frame->left_layout, frame->right_layout);
1205 compile_tbar_layout (tbar_layout_col, od->default_tbar_elem_col,
1206 frame->left_layout, frame->right_layout);
1207
1208 #if defined(LOCAL_DEBUG) && !defined(NO_DEBUG_OUTPU)
1209 for (i = 0; i < MYFRAME_TITLE_BACKS; ++i) {
1210 LOCAL_DEBUG_OUT ("TitlebarLayout col[%d] = %d", i,
1211 tbar_layout_col[i]);
1212 LOCAL_DEBUG_OUT ("TitlebarLayout row[%d] = %d", i,
1213 tbar_layout_row[i]);
1214 }
1215 #endif
1216
1217 for (i = MYFRAME_TITLE_BACK_LBTN; i < MYFRAME_TITLE_BACKS; ++i)
1218 if (frame->title_backs[i] && frame->title_backs[i]->image) {
1219 LOCAL_DEBUG_OUT ("Adding Title Back #%d", i);
1220 if (frame->title_backs_slicing[i].flags != 0) {
1221 ASImage *im = frame->title_backs[i]->image;
1222 int xs = 0, xe = 0, ys = im->width, ye = im->height;
1223 geometry2slicing (frame->title_backs_slicing[i], &xs, &xe, &ys,
1224 &ye);
1225 add_astbar_image (asw->tbar,
1226 tbar_layout_col[ASO_TBAR_ELEM_LBTN + i],
1227 tbar_layout_row[ASO_TBAR_ELEM_LBTN + i],
1228 od->flip,
1229 fix_background_align (frame->
1230 title_backs_align[i]),
1231 im, xs, xe, ys, ye);
1232 } else
1233 add_astbar_icon (asw->tbar,
1234 tbar_layout_col[ASO_TBAR_ELEM_LBTN + i],
1235 tbar_layout_row[ASO_TBAR_ELEM_LBTN + i],
1236 od->flip,
1237 fix_background_align (frame->
1238 title_backs_align[i]),
1239 frame->title_backs[i]->image);
1240 if (i == MYFRAME_TITLE_BACK_RTITLE_SPACER)
1241 rtitle_spacer_added = True;
1242 else if (i == MYFRAME_TITLE_BACK_LTITLE_SPACER)
1243 ltitle_spacer_added = True;
1244
1245 }
1246 #if 1
1247 /* special handling to accomodate FIT_LABEL_SIZE alignment of the title */
1248 if (frame->title_backs[MYFRAME_TITLE_BACK_LBL] &&
1249 frame->title_backs[MYFRAME_TITLE_BACK_LBL]->image) {
1250 LOCAL_DEBUG_OUT ("title_back_align = 0x%lX",
1251 frame->title_backs_align[MYFRAME_TITLE_BACK_LBL]);
1252 if (get_flags
1253 (frame->title_backs_align[MYFRAME_TITLE_BACK_LBL],
1254 FIT_LABEL_SIZE)) {
1255 /* left spacer - if we have an icon to go under the label if align is right or center */
1256 if (get_flags (frame->title_align, ALIGN_RIGHT)
1257 && !ltitle_spacer_added)
1258 add_astbar_spacer (asw->tbar,
1259 tbar_layout_col
1260 [ASO_TBAR_ELEM_LTITLE_SPACER],
1261 tbar_layout_row
1262 [ASO_TBAR_ELEM_LTITLE_SPACER], od->flip,
1263 PAD_LEFT, 1, 1);
1264
1265 /* right spacer - if we have an icon to go under the label and align is left or center */
1266 if (get_flags (frame->title_align, ALIGN_LEFT)
1267 && !rtitle_spacer_added)
1268 add_astbar_spacer (asw->tbar,
1269 tbar_layout_col
1270 [ASO_TBAR_ELEM_RTITLE_SPACER],
1271 tbar_layout_row
1272 [ASO_TBAR_ELEM_RTITLE_SPACER], od->flip,
1273 PAD_RIGHT, 1, 1);
1274 title_align = 0;
1275 }
1276 }
1277 #endif
1278
1279 /* label ( goes on top of above pixmap ) */
1280 add_astbar_label (asw->tbar,
1281 tbar_layout_col[ASO_TBAR_ELEM_LBL],
1282 tbar_layout_row[ASO_TBAR_ELEM_LBL],
1283 od->flip,
1284 title_align, frame->title_h_spacing,
1285 frame->title_v_spacing, ASWIN_NAME (asw),
1286 ASWIN_NAME_ENCODING (asw));
1287
1288 /* all the buttons go after the label to be rendered over it */
1289 /* left buttons : */
1290 add_astbar_btnblock (asw->tbar,
1291 tbar_layout_col[ASO_TBAR_ELEM_LBTN],
1292 tbar_layout_row[ASO_TBAR_ELEM_LBTN],
1293 od->flip, frame->left_btn_align,
1294 &(Scr.Look.ordered_buttons[0]), btn_mask,
1295 Scr.Look.button_first_right,
1296 Scr.Look.TitleButtonXOffset[0],
1297 Scr.Look.TitleButtonYOffset[0],
1298 Scr.Look.TitleButtonSpacing[0],
1299 od->left_btn_order);
1300
1301 /* right buttons : */
1302 add_astbar_btnblock (asw->tbar,
1303 tbar_layout_col[ASO_TBAR_ELEM_RBTN],
1304 tbar_layout_row[ASO_TBAR_ELEM_RBTN],
1305 od->flip, frame->right_btn_align,
1306 &(Scr.Look.
1307 ordered_buttons[Scr.Look.button_first_right]),
1308 btn_mask,
1309 TITLE_BUTTONS - Scr.Look.button_first_right,
1310 Scr.Look.TitleButtonXOffset[1],
1311 Scr.Look.TitleButtonYOffset[1],
1312 Scr.Look.TitleButtonSpacing[1],
1313 od->right_btn_order);
1314 /* titlebar balloons */
1315 for (i = 0; i < TITLE_BUTTONS; ++i) {
1316 if (get_flags (btn_mask, C_TButton0 << i)) {
1317 char *str =
1318 list_functions_by_context (C_TButton0 << i, asw->hints);
1319 LOCAL_DEBUG_OUT ("balloon text will be \"%s\"",
1320 str ? str : "none");
1321 set_astbar_balloon2 (asw->tbar, TitlebarBalloons,
1322 C_TButton0 << i, str, AS_Text_ASCII);
1323 if (str)
1324 free (str);
1325 }
1326 }
1327 }
1328 }
1329
1330 if (ASWIN_HFLAGS (asw, AS_WindowOpacity)) {
1331 set_32bit_property (asw->frame, _XA_NET_WM_WINDOW_OPACITY, XA_CARDINAL,
1332 asw->hints->window_opacity);
1333 }
1334
1335
1336 /* we also need to setup label, unfocused/sticky style and tbar sizes -
1337 * it all is done when we change windows state, or move/resize it */
1338 /*since we might have destroyed/created some windows - we have to refresh grabs : */
1339 grab_window_input (asw, False);
1340 if (get_flags (asw->internal_flags, ASWF_WindowComplete)) {
1341 /* we need to map all the possibly created subwindows if window is not iconic */
1342 if (!ASWIN_GET_FLAGS (asw, AS_Iconic)) {
1343 for (i = 0; i < FRAME_SIDES; ++i)
1344 map_canvas_window (asw->frame_sides[i], False);
1345
1346 /* LOCAL_DEBUG_OUT("mapping frame subwindows for client %lX, frame canvas = %p", asw->w, asw->frame_canvas );
1347 XMapSubwindows(dpy, asw->frame); */
1348 } else {
1349 map_canvas_window (asw->icon_canvas, False);
1350 map_canvas_window (asw->icon_title_canvas, False);
1351 }
1352 }
1353
1354 return status_changed;
1355 }
1356
1357
1358 /*************************************************************************/
1359 /* Main window decoration routine */
1360 /*************************************************************************/
redecorate_window(ASWindow * asw,Bool free_resources)1361 void redecorate_window (ASWindow * asw, Bool free_resources)
1362 {
1363 int i;
1364
1365 LOCAL_DEBUG_OUT ("as?w(%p)->free_res(%d)", asw, free_resources);
1366 if (AS_ASSERT (asw))
1367 return;
1368
1369 if (free_resources || asw->hints == NULL || asw->status == NULL) { /* destroy window decorations here : */
1370 /* destruction goes in reverese order ! */
1371 check_tbar (&(asw->icon_title), False, NULL, NULL, 0, 0, 0, 0, 0, 0, 0,
1372 0, C_NO_CONTEXT, NULL);
1373 check_tbar (&(asw->icon_button), False, NULL, NULL, 0, 0, 0, 0, 0, 0,
1374 0, 0, C_NO_CONTEXT, NULL);
1375 check_tbar (&(asw->tbar), False, NULL, NULL, 0, 0, 0, 0, 0, 0, 0, 0,
1376 C_NO_CONTEXT, NULL);
1377 i = FRAME_PARTS;
1378 while (--i >= 0)
1379 check_tbar (&(asw->frame_bars[i]), False, NULL, NULL, 0, 0, 0, 0, 0,
1380 0, 0, 0, C_NO_CONTEXT, NULL);
1381
1382 check_side_canvas (asw, FR_W, False);
1383 check_side_canvas (asw, FR_E, False);
1384 check_side_canvas (asw, FR_S, False);
1385 check_side_canvas (asw, FR_N, False);
1386
1387 if (asw->icon_canvas == asw->icon_title_canvas)
1388 asw->icon_title_canvas = NULL;
1389 if (asw->icon_title_canvas && asw->icon_title_canvas->w)
1390 check_icon_title_canvas (asw, False, False);
1391 if (asw->icon_canvas && asw->icon_canvas->w)
1392 check_icon_canvas (asw, False);
1393 check_client_canvas (asw, False);
1394 check_frame_canvas (asw, False);
1395
1396 return;
1397 }
1398
1399 /* 1) we need to create our frame window : */
1400 if (check_frame_canvas (asw, True) == NULL)
1401 return;
1402
1403 /* 2) we need to reparent our title window : */
1404 if (check_client_canvas (asw, True) == NULL)
1405 return;
1406
1407 hints2decorations (asw, NULL);
1408
1409 }
1410
1411 /****************************************************************************
1412 *
1413 * Sets up the shaped window borders
1414 *
1415 ****************************************************************************/
SetShape(ASWindow * asw,int w)1416 void SetShape (ASWindow * asw, int w)
1417 {
1418 #ifdef SHAPE
1419 LOCAL_DEBUG_CALLER_OUT ("asw(%p)->client(%lX)", asw, asw ? asw->w : 0);
1420
1421 if (asw) {
1422
1423 if (ASWIN_GET_FLAGS (asw, AS_Dead)) {
1424 clear_canvas_shape (asw->frame_canvas, True);
1425 return;
1426 }
1427
1428 if (ASWIN_GET_FLAGS (asw, AS_Iconic)) { /* todo: update icon's shape */
1429
1430 } else {
1431 int i, tbar_side = -1;
1432 int child_x = 0;
1433 int child_y = 0;
1434 unsigned int width, height, bw;
1435 XRectangle rect;
1436
1437 /* starting with an empty list of rectangles */
1438 if (asw->frame_canvas->shape)
1439 flush_vector (asw->frame_canvas->shape);
1440 else
1441 asw->frame_canvas->shape = create_shape ();
1442
1443 get_current_canvas_geometry (asw->client_canvas, &child_x, &child_y,
1444 &width, &height, &bw);
1445 rect.x = 0;
1446 rect.y = 0;
1447 rect.width = width;
1448 rect.height = height;
1449
1450 /* adding rectangles for all the frame decorations */
1451 if (asw->shading_steps == 0 && ASWIN_GET_FLAGS (asw, AS_Shaded)) {
1452 ASOrientation *od = get_orientation_data (asw);
1453 tbar_side = od->tbar_side;
1454 }
1455 for (i = 0; i < FRAME_SIDES; ++i)
1456 if (asw->frame_sides[i] && (i == tbar_side || tbar_side == -1)) {
1457 int x, y;
1458 unsigned int s_width, s_height, bw;
1459 LOCAL_DEBUG_OUT (" Frame side %d", i);
1460 get_current_canvas_geometry (asw->frame_sides[i], &x, &y,
1461 &s_width, &s_height, &bw);
1462
1463 combine_canvas_shape_at_geom (asw->frame_canvas,
1464 asw->frame_sides[i], x, y, s_width,
1465 s_height, bw);
1466 /* combine_canvas_shape( asw->frame_canvas, asw->frame_sides[i] ); */
1467 }
1468
1469 /* subtract client rectangle, before adding clients shape */
1470 subtract_shape_rectangle (asw->frame_canvas->shape, &rect, 1,
1471 child_x, child_y, asw->frame_canvas->width,
1472 asw->frame_canvas->height);
1473 /* add clients shape */
1474 combine_canvas_shape_at_geom (asw->frame_canvas, asw->client_canvas,
1475 child_x, child_y, width, height, bw);
1476
1477 #ifndef NO_DEBUG_OUTPUT
1478 print_shape (asw->frame_canvas->shape);
1479 #endif
1480 /* apply shape */
1481 update_canvas_display_mask (asw->frame_canvas, True);
1482 set_flags (asw->internal_flags, ASWF_PendingShapeRemoval);
1483
1484 }
1485 }
1486 #endif /* SHAPE */
1487 }
1488
ClearShape(ASWindow * asw)1489 void ClearShape (ASWindow * asw)
1490 {
1491 #ifdef SHAPE
1492 if (asw && asw->frame_canvas) {
1493 clear_canvas_shape (asw->frame_canvas, True);
1494 clear_flags (asw->internal_flags, ASWF_PendingShapeRemoval);
1495 }
1496 #endif /* SHAPE */
1497 }
1498