cvsimport
[fvwm.git] / fvwm / update.c
blob22361fc717569d688aa59f83dcde908ba6152a76
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;
101 /* TA: 2010-07-28: Conditionally update window states if they're
102 * present -- i.e., we're preserving states set via Windowstyle.
104 CLEAR_USER_STATES(t, S_USER_STATES(SCM(*pstyle)));
105 SET_USER_STATES(t, S_USER_STATES(SCF(*pstyle)));
107 if (flags->do_setup_focus_policy)
109 setup_focus_policy(t);
110 if (t == focus_w &&
111 !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(t)))
113 focus_w = NULL;
114 if (Scr.Hilite == t)
116 Scr.Hilite = NULL;
118 flags->do_redraw_decoration = True;
121 if (flags->do_update_gnome_styles)
123 if (!S_DO_IGNORE_GNOME_HINTS(SCF(*pstyle)))
125 GNOME_GetStyle(t, pstyle);
128 if (flags->do_update_window_grabs)
130 focus_grab_buttons(t);
132 if (IS_TRANSIENT(t) && flags->do_redecorate_transient)
134 flags->do_redecorate = True;
135 flags->do_update_window_font = True;
139 * is_sticky
140 * is_icon_sticky
142 * These are a bit complicated because they can move windows to a
143 * different page or desk. */
144 ecc.type = EXCT_NULL;
145 ecc.w.fw = t;
146 ecc.w.w = FW_W_FRAME(t);
147 ecc.w.wcontext = C_FRAME;
148 exc = exc_create_context(
149 &ecc, ECC_TYPE | ECC_FW | ECC_W | ECC_WCONTEXT);
150 if (flags->do_update_stick_icon && IS_ICONIFIED(t) &&
151 !(IS_STICKY_ACROSS_PAGES(t) || IS_STICKY_ACROSS_DESKS(t)))
153 if (IS_ICON_STICKY_ACROSS_PAGES(pstyle) ||
154 IS_ICON_STICKY_ACROSS_DESKS(pstyle))
156 /* stick and unstick the window to force the icon on
157 * the current page */
158 handle_stick(
159 NULL, exc, "",
160 S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle)),
161 S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle)), 1, 1);
162 handle_stick(NULL, exc, "", 0, 0, 1, 0);
164 flags->do_update_icon_title = True;
166 else if (flags->do_update_stick)
168 handle_stick(
169 NULL, exc, "", S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle)),
170 S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle)), 0, 0);
172 exc_destroy_context(exc);
173 if (FMiniIconsSupported && flags->do_update_mini_icon)
175 if (!HAS_EWMH_MINI_ICON(t) || DO_EWMH_MINI_ICON_OVERRIDE(t))
177 change_mini_icon(t, pstyle);
179 else
181 if (EWMH_SetIconFromWMIcon(t, NULL, 0, True))
183 SET_HAS_EWMH_MINI_ICON(t, True);
185 else
187 /* "should" not happen */
188 SET_HAS_EWMH_MINI_ICON(t, False);
189 change_mini_icon(t, pstyle);
193 if (flags->do_update_visible_window_name)
195 setup_visible_name(t, False);
196 BroadcastName(M_VISIBLE_NAME,FW_W(t),FW_W_FRAME(t),
197 (unsigned long)t,t->visible_name);
198 EWMH_SetVisibleName(t, False);
201 if (flags->do_update_visible_icon_name)
203 setup_visible_name(t, True);
204 BroadcastName(MX_VISIBLE_ICON_NAME,FW_W(t),FW_W_FRAME(t),
205 (unsigned long)t,t->visible_icon_name);
206 EWMH_SetVisibleName(t, True);
209 if (flags->do_update_window_font || flags->do_update_window_font_height)
211 if (!is_style_initialised)
213 init_style(&old_t, t, pstyle, &buttons);
214 is_style_initialised = True;
216 setup_window_font(t, pstyle, flags->do_update_window_font);
217 flags->do_redecorate = True;
219 if (flags->do_update_title_text_dir)
221 flags->do_redecorate = True;
223 if (flags->do_redecorate || flags->do_update_title_dir)
225 size_borders b_old;
226 size_borders b_new;
227 int dw = 0;
228 int dh = 0;
229 rectangle naked_g;
230 rectangle *new_g;
232 if (flags->do_redecorate)
234 if (!is_style_initialised)
236 init_style(&old_t, t, pstyle, &buttons);
237 is_style_initialised = True;
240 /* redecorate */
241 change_auxiliary_windows(t, buttons);
243 /* calculate the new offsets */
244 /* naked_g: geometry without decor */
245 gravity_get_naked_geometry(
246 old_t.hints.win_gravity, &old_t, &naked_g,
247 &t->g.normal);
248 /* gravity without decor */
249 gravity_translate_to_northwest_geometry_no_bw(
250 old_t.hints.win_gravity, &old_t, &naked_g,
251 &naked_g);
252 /* set g.normal with the decor */
253 gravity_add_decoration(
254 old_t.hints.win_gravity, t, &t->g.normal,
255 &naked_g);
257 if (flags->do_update_title_dir)
259 /* new border sizes */
260 get_window_borders(t, &b_old);
261 SET_TITLE_DIR(t, S_TITLE_DIR(SCF(*pstyle)));
262 setup_title_geometry(t, pstyle);
263 get_window_borders(t, &b_new);
265 /* resizing */
266 dw = b_new.total_size.width - b_old.total_size.width;
267 dh = b_new.total_size.height - b_old.total_size.height;
268 gravity_resize(
269 t->hints.win_gravity, &t->g.normal, dw, dh);
270 gravity_constrain_size(
271 t->hints.win_gravity, t, &t->g.normal, 0);
274 if (IS_MAXIMIZED(t))
276 if (flags->do_redecorate)
278 int off_x = old_t.g.normal.x - old_t.g.max.x;
279 int off_y = old_t.g.normal.y - old_t.g.max.y;
280 int new_off_x;
281 int new_off_y;
283 /* maximized windows are always considered to
284 * have NorthWestGravity */
285 gravity_get_naked_geometry(
286 NorthWestGravity, &old_t, &naked_g,
287 &t->g.max);
288 gravity_translate_to_northwest_geometry_no_bw(
289 NorthWestGravity, &old_t, &naked_g,
290 &naked_g);
291 gravity_add_decoration(
292 NorthWestGravity, t, &t->g.max,
293 &naked_g);
294 /* prevent random paging when unmaximizing
295 * after e.g. the border width has changed */
296 new_off_x = t->g.normal.x - t->g.max.x;
297 new_off_y = t->g.normal.y - t->g.max.y;
298 t->g.max_offset.x += new_off_x - off_x;
299 t->g.max_offset.y += new_off_y - off_y;
301 if (flags->do_update_title_dir)
303 frame_g = t->g.max;
304 gravity_resize(
305 t->hints.win_gravity, &t->g.max, dw,
306 dh);
307 gravity_constrain_size(
308 t->hints.win_gravity, t, &t->g.max,
309 CS_UPDATE_MAX_DEFECT);
311 new_g = &t->g.max;
313 else
315 new_g = &t->g.normal;
317 if (IS_SHADED(t))
319 get_unshaded_geometry(t, new_g);
320 if (USED_TITLE_DIR_FOR_SHADING(t))
322 SET_SHADED_DIR(t, GET_TITLE_DIR(t));
324 get_shaded_geometry(t, &frame_g, new_g);
326 else
328 get_relative_geometry(&frame_g, new_g);
330 flags->do_setup_frame = True;
331 flags->do_redraw_decoration = True;
333 if (flags->do_update_rotated_title)
335 if (t->title_text_rotation != ROTATION_0)
337 flags->do_setup_frame = True;
338 flags->do_redraw_decoration = True;
341 if (flags->do_resize_window)
343 rectangle old_g;
345 setup_frame_size_limits(t, pstyle);
346 old_g = frame_g;
347 frame_g = t->g.normal;
348 gravity_constrain_size(t->hints.win_gravity, t, &frame_g, 0);
349 t->g.normal = frame_g;
350 if (IS_MAXIMIZED(t))
352 frame_g = t->g.max;
353 gravity_constrain_size(
354 t->hints.win_gravity, t, &frame_g,
355 CS_UPDATE_MAX_DEFECT);
356 t->g.max = frame_g;
358 frame_g = old_g;
359 gravity_constrain_size(
360 t->hints.win_gravity, t, &frame_g, 0);
362 flags->do_setup_frame = True;
363 flags->do_redraw_decoration = True;
365 if (flags->do_setup_frame)
367 FvwmWindow *tmp;
369 setup_title_geometry(t, pstyle);
370 /* frame_force_setup_window needs to know if the window is
371 * hilighted */
372 tmp = get_focus_window();
373 set_focus_window(focus_w);
374 frame_force_setup_window(
375 t, frame_g.x, frame_g.y, frame_g.width, frame_g.height,
376 True);
377 set_focus_window(tmp);
378 GNOME_SetWinArea(t);
379 EWMH_SetFrameStrut(t);
381 if (flags->do_update_window_color)
383 if (t != focus_w)
385 flags->do_redraw_decoration = True;
387 update_window_color_style(t, pstyle);
388 if (t != Scr.Hilite)
390 flags->do_broadcast_focus = True;
393 if (flags->do_update_window_color_hi)
395 if (t == focus_w)
397 flags->do_redraw_decoration = True;
399 update_window_color_hi_style(t, pstyle);
400 flags->do_broadcast_focus = True;
401 if (t == Scr.Hilite)
403 flags->do_broadcast_focus = True;
406 if (flags->do_update_icon_title_cs_hi)
408 if (t == focus_w && IS_ICONIFIED(t))
410 flags->do_redraw_icon = True;
412 update_icon_title_cs_hi_style(t, pstyle);
414 if (flags->do_update_icon_title_cs)
416 if (t != focus_w && IS_ICONIFIED(t))
418 flags->do_redraw_icon = True;
420 update_icon_title_cs_style(t, pstyle);
422 if (flags->do_update_icon_background_cs)
424 int old_cs = t->icon_background_cs;
426 update_icon_background_cs_style(t, pstyle);
427 if ((old_cs < 0 && t->icon_background_cs >= 0) ||
428 (old_cs >= 0 && t->icon_background_cs < 0))
430 flags->do_update_icon = True;
432 else
434 flags->do_redraw_icon = True;
437 if (flags->do_update_icon_size_limits)
439 setup_icon_size_limits(t, pstyle);
440 flags->do_update_icon = True;
442 if (flags->do_update_icon_font)
444 if (!is_style_initialised)
446 init_style(&old_t, t, pstyle, &buttons);
447 is_style_initialised = True;
449 setup_icon_font(t, pstyle, flags->do_update_icon_font);
450 flags->do_update_icon_title = True;
452 if (flags->do_update_icon_boxes)
454 change_icon_boxes(t, pstyle);
456 if (flags->do_update_icon)
458 setup_icon_background_parameters(t, pstyle);
459 setup_icon_title_parameters(t, pstyle);
460 change_icon(t, pstyle);
461 flags->do_update_icon_placement = True;
462 flags->do_update_icon_title = False;
463 flags->do_redraw_icon = False;
464 flags->do_update_ewmh_icon = True;
466 if (flags->do_redraw_icon)
468 /* should not test if the window is iconified */
469 DrawIconWindow(t, True, True, False, True, NULL);;
470 flags->do_redraw_decoration = False;
471 flags->do_update_icon_title = False;
473 if (flags->do_update_icon_title)
475 RedoIconName(t);
477 if (flags->do_update_icon_placement)
479 if (IS_ICONIFIED(t))
481 initial_window_options_t win_opts;
483 memset(&win_opts, 0, sizeof(win_opts));
484 SET_ICONIFIED(t, 0);
485 Iconify(t, &win_opts);
486 flags->do_redraw_decoration = False;
489 if (flags->do_redraw_decoration)
491 FvwmWindow *tmp;
493 /* frame_redraw_decorations needs to know if the window is
494 * hilighted */
495 tmp = get_focus_window();
496 set_focus_window(focus_w);
497 if (IS_ICONIFIED(t))
499 DrawIconWindow(t, True, True, False, False, NULL);
501 else
503 border_redraw_decorations(t);
505 set_focus_window(tmp);
507 if (flags->do_update_frame_attributes)
509 setup_frame_attributes(t, pstyle);
511 if (flags->do_update_ewmh_state_hints)
513 EWMH_SetWMState(t, False);
515 if (flags->do_update_modules_flags)
517 BroadcastConfig(M_CONFIGURE_WINDOW,t);
519 if (flags->do_update_ewmh_mini_icon || flags->do_update_ewmh_icon)
521 EWMH_DoUpdateWmIcon(
522 t, flags->do_update_ewmh_mini_icon,
523 flags->do_update_ewmh_icon);
525 if (flags->do_update_placement_penalty)
527 setup_placement_penalty(t, pstyle);
529 if (flags->do_update_working_area)
531 EWMH_UpdateWorkArea();
533 if (flags->do_update_ewmh_stacking_hints)
535 if (DO_EWMH_USE_STACKING_HINTS(t))
537 if (t->ewmh_hint_layer > 0 &&
538 t->layer != t->ewmh_hint_layer)
540 t->ewmh_normal_layer = t->layer;
541 new_layer(t, t->ewmh_hint_layer);
544 else
546 if (t->ewmh_hint_layer > 0 && t->ewmh_normal_layer)
548 if (t->ewmh_normal_layer)
550 new_layer(t, t->ewmh_normal_layer);
552 else
554 new_layer(t, Scr.DefaultLayer);
559 if (flags->do_update_ewmh_allowed_actions)
561 EWMH_SetAllowedActions(t);
563 if (flags->do_broadcast_focus)
565 if (Scr.Hilite != NULL && t == Scr.Hilite)
567 BroadcastPacket(
568 M_FOCUS_CHANGE, 5, (long)FW_W(Scr.Hilite),
569 (long)FW_W_FRAME(Scr.Hilite), (long)0,
570 (long)Scr.Hilite->hicolors.fore,
571 (long)Scr.Hilite->hicolors.back);
574 if (flags->do_refresh)
576 if (!IS_ICONIFIED(t))
578 refresh_window(FW_W_FRAME(t), False);
581 setup_numeric_vals(t, pstyle);
582 if (flags->do_update_cr_motion_method)
584 switch (SCR_MOTION_METHOD(&pstyle->flags))
586 case WS_CR_MOTION_METHOD_AUTO:
587 if (WAS_CR_MOTION_METHOD_DETECTED(t))
589 /* method was already detected, keep it */
590 break;
592 /* fall through */
593 case WS_CR_MOTION_METHOD_USE_GRAV:
594 case WS_CR_MOTION_METHOD_STATIC_GRAV:
595 SET_CR_MOTION_METHOD(
596 t, SCR_MOTION_METHOD(&pstyle->flags));
597 SET_CR_MOTION_METHOD_DETECTED(t, 0);
598 break;
602 if (flags->do_update_layer)
604 int layer = get_layer(t);
606 if (SUSE_LAYER(&pstyle->flags))
608 /* use layer from style */
609 layer = SGET_LAYER(*pstyle);
612 /* Set the layer, and modify the stack ring. */
613 new_layer(t, layer);
616 return;
619 /* ---------------------------- builtin commands --------------------------- */
621 /* takes only care of destroying windows that have to go away. */
622 void destroy_scheduled_windows(void)
624 flist *t;
625 Bool do_need_ungrab = False;
627 if (Scr.flags.is_executing_complex_function ||
628 Scr.flags.is_executing_menu_function ||
629 !Scr.flags.is_window_scheduled_for_destroy)
631 return;
633 /* Grab the server during the style update! */
634 if (GrabEm(CRS_WAIT, GRAB_BUSY))
636 do_need_ungrab = True;
638 MyXGrabServer(dpy);
639 Scr.flags.is_window_scheduled_for_destroy = 0;
640 /* need to destroy one or more windows before looking at the window
641 * list */
642 for (t = Scr.FWScheduledForDestroy; t != NULL; t = t->next)
644 destroy_window(t->object);
646 Scr.FWScheduledForDestroy = flist_free_list(Scr.FWScheduledForDestroy);
647 MyXUngrabServer(dpy);
648 if (do_need_ungrab)
650 UngrabEm(GRAB_BUSY);
653 return;
656 /* similar to the flush_window_updates() function, but does only the updates
657 * for a single window whose decor has been changed. */
658 void apply_decor_change(FvwmWindow *fw)
660 window_style style;
661 update_win flags;
663 lookup_style(fw, &style);
664 memset(&flags, 0, sizeof(flags));
665 flags.do_redecorate = True;
666 flags.do_update_window_font_height = True;
667 apply_window_updates(fw, &flags, &style, get_focus_window());
669 return;
672 /* Check and apply new style to each window if the style has changed. */
673 void flush_window_updates(void)
675 FvwmWindow *t;
676 window_style style;
677 FvwmWindow *focus_fw;
678 Bool do_need_ungrab = False;
679 update_win flags;
681 /* Grab the server during the style update! */
682 if (GrabEm(CRS_WAIT, GRAB_BUSY))
684 do_need_ungrab = True;
686 MyXGrabServer(dpy);
688 /* This is necessary in case the focus policy changes. With
689 * ClickToFocus some buttons have to be grabbed/ungrabbed. */
690 focus_fw = get_focus_window();
691 DeleteFocus(False);
693 /* Apply the new default font and colours first */
694 if (Scr.flags.has_default_color_changed ||
695 Scr.flags.has_default_font_changed)
697 ApplyDefaultFontAndColors();
700 /* update styles for all windows */
701 for (t = Scr.FvwmRoot.next; t != NULL; t = t->next)
703 memset(&flags, 0, sizeof(update_win));
704 check_window_style_change(t, &flags, &style);
705 if (Scr.flags.has_xinerama_state_changed)
707 flags.do_update_icon_boxes = True;
708 flags.do_update_icon_placement = True;
710 if (Scr.flags.has_nr_buttons_changed)
712 flags.do_redecorate = True;
714 /* TODO: this is not optimised for minimal redrawing yet*/
715 if (t->decor->flags.has_changed)
717 flags.do_redecorate = True;
718 flags.do_update_window_font_height = True;
720 if (Scr.flags.has_default_font_changed && !HAS_ICON_FONT(t))
722 flags.do_update_icon_font = True;
724 if (Scr.flags.has_default_font_changed && !HAS_WINDOW_FONT(t))
726 flags.do_update_window_font = True;
728 if (t->decor->flags.has_title_height_changed)
730 flags.do_update_window_font_height = True;
732 if (Scr.flags.has_mouse_binding_changed)
734 flags.do_update_window_grabs = True;
736 /* now apply the changes */
737 apply_window_updates(t, &flags, &style, focus_fw);
740 /* restore the focus; also handles the case that the previously focused
741 * window is now NeverFocus */
742 if (focus_fw)
744 SetFocusWindow(focus_fw, False, FOCUS_SET_FORCE);
745 if (Scr.flags.has_mouse_binding_changed)
747 focus_grab_buttons(focus_fw);
750 else
752 DeleteFocus(True);
755 /* finally clean up the change flags */
756 reset_style_changes();
757 reset_decor_changes();
758 Scr.flags.do_need_window_update = 0;
759 Scr.flags.has_default_font_changed = 0;
760 Scr.flags.has_default_color_changed = 0;
761 Scr.flags.has_mouse_binding_changed = 0;
762 Scr.flags.has_nr_buttons_changed = 0;
763 Scr.flags.has_xinerama_state_changed = 0;
765 MyXUngrabServer(dpy);
766 if (do_need_ungrab)
768 UngrabEm(GRAB_BUSY);
771 return;
774 void CMD_UpdateStyles(F_CMD_ARGS)
776 if (Scr.flags.do_need_window_update)
778 flush_window_updates();
781 return;