Correct typo of dates in Changelog.
[fvwm.git] / fvwm / update.c
blobd6117b5e1d510f7d7992ed29e1acabd9b43bea44
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 /* ---------------------------- included header files ---------------------- */
19 #include "config.h"
20 #include <stdio.h>
22 #include "libs/fvwmlib.h"
23 #include "libs/charmap.h"
24 #include "libs/wcontext.h"
25 #include "libs/Grab.h"
26 #include "fvwm.h"
27 #include "externs.h"
28 #include "execcontext.h"
29 #include "cursor.h"
30 #include "bindings.h"
31 #include "misc.h"
32 #include "screen.h"
33 #include "update.h"
34 #include "style.h"
35 #include "builtins.h"
36 #include "borders.h"
37 #include "frame.h"
38 #include "gnome.h"
39 #include "ewmh.h"
40 #include "icons.h"
41 #include "geometry.h"
42 #include "move_resize.h"
43 #include "add_window.h"
44 #include "module_interface.h"
45 #include "focus.h"
46 #include "stack.h"
47 #include "icons.h"
49 /* ---------------------------- local definitions -------------------------- */
51 /* ---------------------------- local macros ------------------------------- */
53 /* ---------------------------- imports ------------------------------------ */
55 /* ---------------------------- included code files ------------------------ */
57 /* ---------------------------- local types -------------------------------- */
59 /* ---------------------------- forward declarations ----------------------- */
61 /* ---------------------------- local variables ---------------------------- */
63 /* ---------------------------- exported variables (globals) --------------- */
65 /* ---------------------------- local functions ---------------------------- */
67 /* ---------------------------- interface functions ------------------------ */
69 static void init_style(
70 FvwmWindow *old_t, FvwmWindow *t, window_style *pstyle,
71 short *pbuttons)
73 /* copy the window structure because we still need some old values. */
74 memcpy(old_t, t, sizeof(FvwmWindow));
75 /* determine level of decoration */
76 setup_style_and_decor(t, pstyle, pbuttons);
77 /* restore some old values */
78 IS_STICKY_ACROSS_PAGES(t) = IS_STICKY_ACROSS_PAGES(old_t);
79 IS_STICKY_ACROSS_DESKS(t) = IS_STICKY_ACROSS_DESKS(old_t);
80 GET_USER_STATES(t) = GET_USER_STATES(old_t);
82 return;
85 static void apply_window_updates(
86 FvwmWindow *t, update_win *flags, window_style *pstyle,
87 FvwmWindow *focus_w)
89 FvwmWindow old_t;
90 short buttons;
91 Bool is_style_initialised = False;
92 rectangle frame_g;
93 const exec_context_t *exc;
94 exec_context_changes_t ecc;
96 frame_g.x = t->g.frame.x;
97 frame_g.y = t->g.frame.y;
98 frame_g.width = t->g.frame.width;
99 frame_g.height = t->g.frame.height;
100 if (flags->do_setup_focus_policy)
102 setup_focus_policy(t);
103 if (t == focus_w &&
104 !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(t)))
106 focus_w = NULL;
107 if (Scr.Hilite == t)
109 Scr.Hilite = NULL;
111 flags->do_redraw_decoration = True;
114 if (flags->do_update_gnome_styles)
116 if (!S_DO_IGNORE_GNOME_HINTS(SCF(*pstyle)))
118 GNOME_GetStyle(t, pstyle);
121 if (flags->do_update_window_grabs)
123 focus_grab_buttons(t);
125 if (IS_TRANSIENT(t) && flags->do_redecorate_transient)
127 flags->do_redecorate = True;
128 flags->do_update_window_font = True;
132 * is_sticky
133 * is_icon_sticky
135 * These are a bit complicated because they can move windows to a
136 * different page or desk. */
137 ecc.type = EXCT_NULL;
138 ecc.w.fw = t;
139 ecc.w.w = FW_W_FRAME(t);
140 ecc.w.wcontext = C_FRAME;
141 exc = exc_create_context(
142 &ecc, ECC_TYPE | ECC_FW | ECC_W | ECC_WCONTEXT);
143 if (flags->do_update_stick_icon && IS_ICONIFIED(t) &&
144 !(IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t)))
146 if (IS_ICON_STICKY_ACROSS_PAGES(pstyle) ||
147 IS_ICON_STICKY_ACROSS_DESKS(pstyle))
149 /* stick and unstick the window to force the icon on
150 * the current page */
151 handle_stick(
152 NULL, exc, "",
153 S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle)),
154 S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle)), 1, 1);
155 handle_stick(NULL, exc, "", 0, 0, 1, 0);
157 flags->do_update_icon_title = True;
159 else if (flags->do_update_stick)
161 handle_stick(
162 NULL, exc, "", S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle)),
163 S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle)), 0, 0);
165 exc_destroy_context(exc);
166 if (FMiniIconsSupported && flags->do_update_mini_icon)
168 if (!HAS_EWMH_MINI_ICON(t) || DO_EWMH_MINI_ICON_OVERRIDE(t))
170 change_mini_icon(t, pstyle);
172 else
174 if (EWMH_SetIconFromWMIcon(t, NULL, 0, True))
176 SET_HAS_EWMH_MINI_ICON(t, True);
178 else
180 /* "should" not happen */
181 SET_HAS_EWMH_MINI_ICON(t, False);
182 change_mini_icon(t, pstyle);
186 if (flags->do_update_visible_window_name)
188 setup_visible_name(t, False);
189 BroadcastName(M_VISIBLE_NAME,FW_W(t),FW_W_FRAME(t),
190 (unsigned long)t,t->visible_name);
191 EWMH_SetVisibleName(t, False);
194 if (flags->do_update_visible_icon_name)
196 setup_visible_name(t, True);
197 BroadcastName(MX_VISIBLE_ICON_NAME,FW_W(t),FW_W_FRAME(t),
198 (unsigned long)t,t->visible_icon_name);
199 EWMH_SetVisibleName(t, True);
202 if (flags->do_update_window_font || flags->do_update_window_font_height)
204 if (!is_style_initialised)
206 init_style(&old_t, t, pstyle, &buttons);
207 is_style_initialised = True;
209 setup_window_font(t, pstyle, flags->do_update_window_font);
210 flags->do_redecorate = True;
212 if (flags->do_update_title_text_dir)
214 flags->do_redecorate = True;
216 if (flags->do_redecorate || flags->do_update_title_dir)
218 size_borders b_old;
219 size_borders b_new;
220 int dw = 0;
221 int dh = 0;
222 rectangle naked_g;
223 rectangle *new_g;
225 if (flags->do_redecorate)
227 if (!is_style_initialised)
229 init_style(&old_t, t, pstyle, &buttons);
230 is_style_initialised = True;
233 /* redecorate */
234 change_auxiliary_windows(t, buttons);
236 /* calculate the new offsets */
237 /* naked_g: geometry without decor */
238 gravity_get_naked_geometry(
239 old_t.hints.win_gravity, &old_t, &naked_g,
240 &t->g.normal);
241 /* gravity without decor */
242 gravity_translate_to_northwest_geometry_no_bw(
243 old_t.hints.win_gravity, &old_t, &naked_g,
244 &naked_g);
245 /* set g.normal with the decor */
246 gravity_add_decoration(
247 old_t.hints.win_gravity, t, &t->g.normal,
248 &naked_g);
250 if (flags->do_update_title_dir)
252 /* new border sizes */
253 get_window_borders(t, &b_old);
254 SET_TITLE_DIR(t, S_TITLE_DIR(SCF(*pstyle)));
255 setup_title_geometry(t, pstyle);
256 get_window_borders(t, &b_new);
258 /* resizing */
259 dw = b_new.total_size.width - b_old.total_size.width;
260 dh = b_new.total_size.height - b_old.total_size.height;
261 gravity_resize(
262 t->hints.win_gravity, &t->g.normal, dw, dh);
263 gravity_constrain_size(
264 t->hints.win_gravity, t, &t->g.normal, 0);
267 if (IS_MAXIMIZED(t))
269 if (flags->do_redecorate)
271 int off_x = old_t.g.normal.x - old_t.g.max.x;
272 int off_y = old_t.g.normal.y - old_t.g.max.y;
273 int new_off_x;
274 int new_off_y;
276 /* maximized windows are always considered to
277 * have NorthWestGravity */
278 gravity_get_naked_geometry(
279 NorthWestGravity, &old_t, &naked_g,
280 &t->g.max);
281 gravity_translate_to_northwest_geometry_no_bw(
282 NorthWestGravity, &old_t, &naked_g,
283 &naked_g);
284 gravity_add_decoration(
285 NorthWestGravity, t, &t->g.max,
286 &naked_g);
287 /* prevent random paging when unmaximizing
288 * after e.g. the border width has changed */
289 new_off_x = t->g.normal.x - t->g.max.x;
290 new_off_y = t->g.normal.y - t->g.max.y;
291 t->g.max_offset.x += new_off_x - off_x;
292 t->g.max_offset.y += new_off_y - off_y;
294 if (flags->do_update_title_dir)
296 frame_g = t->g.max;
297 gravity_resize(
298 t->hints.win_gravity, &t->g.max, dw,
299 dh);
300 gravity_constrain_size(
301 t->hints.win_gravity, t, &t->g.max,
302 CS_UPDATE_MAX_DEFECT);
304 new_g = &t->g.max;
306 else
308 new_g = &t->g.normal;
310 if (IS_SHADED(t))
312 get_unshaded_geometry(t, new_g);
313 if (USED_TITLE_DIR_FOR_SHADING(t))
315 SET_SHADED_DIR(t, GET_TITLE_DIR(t));
317 get_shaded_geometry(t, &frame_g, new_g);
319 else
321 get_relative_geometry(&frame_g, new_g);
323 flags->do_setup_frame = True;
324 flags->do_redraw_decoration = True;
326 if (flags->do_update_rotated_title)
328 if (t->title_text_rotation != ROTATION_0)
330 flags->do_setup_frame = True;
331 flags->do_redraw_decoration = True;
334 if (flags->do_resize_window)
336 rectangle old_g;
338 setup_frame_size_limits(t, pstyle);
339 old_g = frame_g;
340 frame_g = t->g.normal;
341 gravity_constrain_size(t->hints.win_gravity, t, &frame_g, 0);
342 t->g.normal = frame_g;
343 if (IS_MAXIMIZED(t))
345 frame_g = t->g.max;
346 gravity_constrain_size(
347 t->hints.win_gravity, t, &frame_g,
348 CS_UPDATE_MAX_DEFECT);
349 t->g.max = frame_g;
351 frame_g = old_g;
352 gravity_constrain_size(
353 t->hints.win_gravity, t, &frame_g, 0);
355 flags->do_setup_frame = True;
356 flags->do_redraw_decoration = True;
358 if (flags->do_setup_frame)
360 FvwmWindow *tmp;
362 setup_title_geometry(t, pstyle);
363 /* frame_force_setup_window needs to know if the window is
364 * hilighted */
365 tmp = get_focus_window();
366 set_focus_window(focus_w);
367 frame_force_setup_window(
368 t, frame_g.x, frame_g.y, frame_g.width, frame_g.height,
369 True);
370 set_focus_window(tmp);
371 GNOME_SetWinArea(t);
372 EWMH_SetFrameStrut(t);
374 if (flags->do_update_window_color)
376 if (t != focus_w)
378 flags->do_redraw_decoration = True;
380 update_window_color_style(t, pstyle);
381 if (t != Scr.Hilite)
383 flags->do_broadcast_focus = True;
386 if (flags->do_update_window_color_hi)
388 if (t == focus_w)
390 flags->do_redraw_decoration = True;
392 update_window_color_hi_style(t, pstyle);
393 flags->do_broadcast_focus = True;
394 if (t == Scr.Hilite)
396 flags->do_broadcast_focus = True;
399 if (flags->do_update_icon_title_cs_hi)
401 if (t == focus_w && IS_ICONIFIED(t))
403 flags->do_redraw_icon = True;
405 update_icon_title_cs_hi_style(t, pstyle);
407 if (flags->do_update_icon_title_cs)
409 if (t != focus_w && IS_ICONIFIED(t))
411 flags->do_redraw_icon = True;
413 update_icon_title_cs_style(t, pstyle);
415 if (flags->do_update_icon_background_cs)
417 int old_cs = t->icon_background_cs;
419 update_icon_background_cs_style(t, pstyle);
420 if ((old_cs < 0 && t->icon_background_cs >= 0) ||
421 (old_cs >= 0 && t->icon_background_cs < 0))
423 flags->do_update_icon = True;
425 else
427 flags->do_redraw_icon = True;
430 if (flags->do_update_icon_size_limits)
432 setup_icon_size_limits(t, pstyle);
433 flags->do_update_icon = True;
435 if (flags->do_update_icon_font)
437 if (!is_style_initialised)
439 init_style(&old_t, t, pstyle, &buttons);
440 is_style_initialised = True;
442 setup_icon_font(t, pstyle, flags->do_update_icon_font);
443 flags->do_update_icon_title = True;
445 if (flags->do_update_icon_boxes)
447 change_icon_boxes(t, pstyle);
449 if (flags->do_update_icon)
451 setup_icon_background_parameters(t, pstyle);
452 setup_icon_title_parameters(t, pstyle);
453 change_icon(t, pstyle);
454 flags->do_update_icon_placement = True;
455 flags->do_update_icon_title = False;
456 flags->do_redraw_icon = False;
457 flags->do_update_ewmh_icon = True;
459 if (flags->do_redraw_icon)
461 /* should not test if the window is iconified */
462 DrawIconWindow(t, True, True, False, True, NULL);;
463 flags->do_redraw_decoration = False;
464 flags->do_update_icon_title = False;
466 if (flags->do_update_icon_title)
468 RedoIconName(t);
470 if (flags->do_update_icon_placement)
472 if (IS_ICONIFIED(t))
474 initial_window_options_t win_opts;
476 memset(&win_opts, 0, sizeof(win_opts));
477 SET_ICONIFIED(t, 0);
478 Iconify(t, &win_opts);
479 flags->do_redraw_decoration = False;
482 if (flags->do_redraw_decoration)
484 FvwmWindow *tmp;
486 /* frame_redraw_decorations needs to know if the window is
487 * hilighted */
488 tmp = get_focus_window();
489 set_focus_window(focus_w);
490 if (IS_ICONIFIED(t))
492 DrawIconWindow(t, True, True, False, False, NULL);
494 else
496 border_redraw_decorations(t);
498 set_focus_window(tmp);
500 if (flags->do_update_frame_attributes)
502 setup_frame_attributes(t, pstyle);
504 if (flags->do_update_ewmh_state_hints)
506 EWMH_SetWMState(t, False);
508 if (flags->do_update_modules_flags)
510 BroadcastConfig(M_CONFIGURE_WINDOW,t);
512 if (flags->do_update_ewmh_mini_icon || flags->do_update_ewmh_icon)
514 EWMH_DoUpdateWmIcon(
515 t, flags->do_update_ewmh_mini_icon,
516 flags->do_update_ewmh_icon);
518 if (flags->do_update_placement_penalty)
520 setup_placement_penalty(t, pstyle);
522 if (flags->do_update_working_area)
524 EWMH_UpdateWorkArea();
526 if (flags->do_update_ewmh_stacking_hints)
528 if (DO_EWMH_USE_STACKING_HINTS(t))
530 if (t->ewmh_hint_layer > 0 &&
531 t->layer != t->ewmh_hint_layer)
533 t->ewmh_normal_layer = t->layer;
534 new_layer(t, t->ewmh_hint_layer);
537 else
539 if (t->ewmh_hint_layer > 0 && t->ewmh_normal_layer)
541 if (t->ewmh_normal_layer)
543 new_layer(t, t->ewmh_normal_layer);
545 else
547 new_layer(t, Scr.DefaultLayer);
552 if (flags->do_update_ewmh_allowed_actions)
554 EWMH_SetAllowedActions(t);
556 if (flags->do_broadcast_focus)
558 if (Scr.Hilite != NULL && t == Scr.Hilite)
560 BroadcastPacket(
561 M_FOCUS_CHANGE, 5, (long)FW_W(Scr.Hilite),
562 (long)FW_W_FRAME(Scr.Hilite), (long)0,
563 (long)Scr.Hilite->hicolors.fore,
564 (long)Scr.Hilite->hicolors.back);
567 if (flags->do_refresh)
569 if (!IS_ICONIFIED(t))
571 refresh_window(FW_W_FRAME(t), False);
574 setup_numeric_vals(t, pstyle);
575 if (flags->do_update_cr_motion_method)
577 switch (SCR_MOTION_METHOD(&pstyle->flags))
579 case WS_CR_MOTION_METHOD_AUTO:
580 if (WAS_CR_MOTION_METHOD_DETECTED(t))
582 /* method was already detected, keep it */
583 break;
585 /* fall through */
586 case WS_CR_MOTION_METHOD_USE_GRAV:
587 case WS_CR_MOTION_METHOD_STATIC_GRAV:
588 SET_CR_MOTION_METHOD(
589 t, SCR_MOTION_METHOD(&pstyle->flags));
590 SET_CR_MOTION_METHOD_DETECTED(t, 0);
591 break;
595 return;
598 /* ---------------------------- builtin commands --------------------------- */
600 /* takes only care of destroying windows that have to go away. */
601 void destroy_scheduled_windows(void)
603 flist *t;
604 Bool do_need_ungrab = False;
606 if (Scr.flags.is_executing_complex_function ||
607 Scr.flags.is_executing_menu_function ||
608 !Scr.flags.is_window_scheduled_for_destroy)
610 return;
612 /* Grab the server during the style update! */
613 if (GrabEm(CRS_WAIT, GRAB_BUSY))
615 do_need_ungrab = True;
617 MyXGrabServer(dpy);
618 Scr.flags.is_window_scheduled_for_destroy = 0;
619 /* need to destroy one or more windows before looking at the window
620 * list */
621 for (t = Scr.FWScheduledForDestroy; t != NULL; t = t->next)
623 destroy_window(t->object);
625 Scr.FWScheduledForDestroy = flist_free_list(Scr.FWScheduledForDestroy);
626 MyXUngrabServer(dpy);
627 if (do_need_ungrab)
629 UngrabEm(GRAB_BUSY);
632 return;
635 /* similar to the flush_window_updates() function, but does only the updates
636 * for a single window whose decor has been changed. */
637 void apply_decor_change(FvwmWindow *fw)
639 window_style style;
640 update_win flags;
642 lookup_style(fw, &style);
643 memset(&flags, 0, sizeof(flags));
644 flags.do_redecorate = True;
645 flags.do_update_window_font_height = True;
646 apply_window_updates(fw, &flags, &style, get_focus_window());
648 return;
651 /* Check and apply new style to each window if the style has changed. */
652 void flush_window_updates(void)
654 FvwmWindow *t;
655 window_style style;
656 FvwmWindow *focus_fw;
657 Bool do_need_ungrab = False;
658 update_win flags;
660 /* Grab the server during the style update! */
661 if (GrabEm(CRS_WAIT, GRAB_BUSY))
663 do_need_ungrab = True;
665 MyXGrabServer(dpy);
667 /* This is necessary in case the focus policy changes. With
668 * ClickToFocus some buttons have to be grabbed/ungrabbed. */
669 focus_fw = get_focus_window();
670 DeleteFocus(False);
672 /* Apply the new default font and colours first */
673 if (Scr.flags.has_default_color_changed ||
674 Scr.flags.has_default_font_changed)
676 ApplyDefaultFontAndColors();
679 /* update styles for all windows */
680 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
682 memset(&flags, 0, sizeof(update_win));
683 check_window_style_change(t, &flags, &style);
684 if (Scr.flags.has_xinerama_state_changed)
686 flags.do_update_icon_boxes = True;
687 flags.do_update_icon_placement = True;
689 if (Scr.flags.has_nr_buttons_changed)
691 flags.do_redecorate = True;
693 /* TODO: this is not optimised for minimal redrawing yet*/
694 if (t->decor->flags.has_changed)
696 flags.do_redecorate = True;
697 flags.do_update_window_font_height = True;
699 if (Scr.flags.has_default_font_changed && !HAS_ICON_FONT(t))
701 flags.do_update_icon_font = True;
703 if (Scr.flags.has_default_font_changed && !HAS_WINDOW_FONT(t))
705 flags.do_update_window_font = True;
707 if (t->decor->flags.has_title_height_changed)
709 flags.do_update_window_font_height = True;
711 if (Scr.flags.has_mouse_binding_changed)
713 flags.do_update_window_grabs = True;
715 /* now apply the changes */
716 apply_window_updates(t, &flags, &style, focus_fw);
719 /* restore the focus; also handles the case that the previously focused
720 * window is now NeverFocus */
721 if (focus_fw)
723 SetFocusWindow(focus_fw, False, FOCUS_SET_FORCE);
724 if (Scr.flags.has_mouse_binding_changed)
726 focus_grab_buttons(focus_fw);
729 else
731 DeleteFocus(True);
734 /* finally clean up the change flags */
735 reset_style_changes();
736 reset_decor_changes();
737 Scr.flags.do_need_window_update = 0;
738 Scr.flags.has_default_font_changed = 0;
739 Scr.flags.has_default_color_changed = 0;
740 Scr.flags.has_mouse_binding_changed = 0;
741 Scr.flags.has_nr_buttons_changed = 0;
742 Scr.flags.has_xinerama_state_changed = 0;
744 MyXUngrabServer(dpy);
745 if (do_need_ungrab)
747 UngrabEm(GRAB_BUSY);
750 return;
753 void CMD_UpdateStyles(F_CMD_ARGS)
755 if (Scr.flags.do_need_window_update)
757 flush_window_updates();
760 return;