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 ---------------------- */
22 #include "libs/fvwmlib.h"
23 #include "libs/charmap.h"
24 #include "libs/wcontext.h"
25 #include "libs/Grab.h"
28 #include "execcontext.h"
42 #include "move_resize.h"
43 #include "add_window.h"
44 #include "module_interface.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
,
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
);
85 static void apply_window_updates(
86 FvwmWindow
*t
, update_win
*flags
, window_style
*pstyle
,
91 Bool is_style_initialised
= False
;
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 GET_USER_STATES(t
) = S_USER_STATES(SCF(*pstyle
));
106 if (flags
->do_setup_focus_policy
)
108 setup_focus_policy(t
);
110 !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(t
)))
117 flags
->do_redraw_decoration
= True
;
120 if (flags
->do_update_gnome_styles
)
122 if (!S_DO_IGNORE_GNOME_HINTS(SCF(*pstyle
)))
124 GNOME_GetStyle(t
, pstyle
);
127 if (flags
->do_update_window_grabs
)
129 focus_grab_buttons(t
);
131 if (IS_TRANSIENT(t
) && flags
->do_redecorate_transient
)
133 flags
->do_redecorate
= True
;
134 flags
->do_update_window_font
= True
;
141 * These are a bit complicated because they can move windows to a
142 * different page or desk. */
143 ecc
.type
= EXCT_NULL
;
145 ecc
.w
.w
= FW_W_FRAME(t
);
146 ecc
.w
.wcontext
= C_FRAME
;
147 exc
= exc_create_context(
148 &ecc
, ECC_TYPE
| ECC_FW
| ECC_W
| ECC_WCONTEXT
);
149 if (flags
->do_update_stick_icon
&& IS_ICONIFIED(t
) &&
150 !(IS_STICKY_ACROSS_PAGES(t
) || IS_STICKY_ACROSS_DESKS(t
)))
152 if (IS_ICON_STICKY_ACROSS_PAGES(pstyle
) ||
153 IS_ICON_STICKY_ACROSS_DESKS(pstyle
))
155 /* stick and unstick the window to force the icon on
156 * the current page */
159 S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle
)),
160 S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle
)), 1, 1);
161 handle_stick(NULL
, exc
, "", 0, 0, 1, 0);
163 flags
->do_update_icon_title
= True
;
165 else if (flags
->do_update_stick
)
168 NULL
, exc
, "", S_IS_STICKY_ACROSS_PAGES(SCF(*pstyle
)),
169 S_IS_STICKY_ACROSS_DESKS(SCF(*pstyle
)), 0, 0);
171 exc_destroy_context(exc
);
172 if (FMiniIconsSupported
&& flags
->do_update_mini_icon
)
174 if (!HAS_EWMH_MINI_ICON(t
) || DO_EWMH_MINI_ICON_OVERRIDE(t
))
176 change_mini_icon(t
, pstyle
);
180 if (EWMH_SetIconFromWMIcon(t
, NULL
, 0, True
))
182 SET_HAS_EWMH_MINI_ICON(t
, True
);
186 /* "should" not happen */
187 SET_HAS_EWMH_MINI_ICON(t
, False
);
188 change_mini_icon(t
, pstyle
);
192 if (flags
->do_update_visible_window_name
)
194 setup_visible_name(t
, False
);
195 BroadcastName(M_VISIBLE_NAME
,FW_W(t
),FW_W_FRAME(t
),
196 (unsigned long)t
,t
->visible_name
);
197 EWMH_SetVisibleName(t
, False
);
200 if (flags
->do_update_visible_icon_name
)
202 setup_visible_name(t
, True
);
203 BroadcastName(MX_VISIBLE_ICON_NAME
,FW_W(t
),FW_W_FRAME(t
),
204 (unsigned long)t
,t
->visible_icon_name
);
205 EWMH_SetVisibleName(t
, True
);
208 if (flags
->do_update_window_font
|| flags
->do_update_window_font_height
)
210 if (!is_style_initialised
)
212 init_style(&old_t
, t
, pstyle
, &buttons
);
213 is_style_initialised
= True
;
215 setup_window_font(t
, pstyle
, flags
->do_update_window_font
);
216 flags
->do_redecorate
= True
;
218 if (flags
->do_update_title_text_dir
)
220 flags
->do_redecorate
= True
;
222 if (flags
->do_redecorate
|| flags
->do_update_title_dir
)
231 if (flags
->do_redecorate
)
233 if (!is_style_initialised
)
235 init_style(&old_t
, t
, pstyle
, &buttons
);
236 is_style_initialised
= True
;
240 change_auxiliary_windows(t
, buttons
);
242 /* calculate the new offsets */
243 /* naked_g: geometry without decor */
244 gravity_get_naked_geometry(
245 old_t
.hints
.win_gravity
, &old_t
, &naked_g
,
247 /* gravity without decor */
248 gravity_translate_to_northwest_geometry_no_bw(
249 old_t
.hints
.win_gravity
, &old_t
, &naked_g
,
251 /* set g.normal with the decor */
252 gravity_add_decoration(
253 old_t
.hints
.win_gravity
, t
, &t
->g
.normal
,
256 if (flags
->do_update_title_dir
)
258 /* new border sizes */
259 get_window_borders(t
, &b_old
);
260 SET_TITLE_DIR(t
, S_TITLE_DIR(SCF(*pstyle
)));
261 setup_title_geometry(t
, pstyle
);
262 get_window_borders(t
, &b_new
);
265 dw
= b_new
.total_size
.width
- b_old
.total_size
.width
;
266 dh
= b_new
.total_size
.height
- b_old
.total_size
.height
;
268 t
->hints
.win_gravity
, &t
->g
.normal
, dw
, dh
);
269 gravity_constrain_size(
270 t
->hints
.win_gravity
, t
, &t
->g
.normal
, 0);
275 if (flags
->do_redecorate
)
277 int off_x
= old_t
.g
.normal
.x
- old_t
.g
.max
.x
;
278 int off_y
= old_t
.g
.normal
.y
- old_t
.g
.max
.y
;
282 /* maximized windows are always considered to
283 * have NorthWestGravity */
284 gravity_get_naked_geometry(
285 NorthWestGravity
, &old_t
, &naked_g
,
287 gravity_translate_to_northwest_geometry_no_bw(
288 NorthWestGravity
, &old_t
, &naked_g
,
290 gravity_add_decoration(
291 NorthWestGravity
, t
, &t
->g
.max
,
293 /* prevent random paging when unmaximizing
294 * after e.g. the border width has changed */
295 new_off_x
= t
->g
.normal
.x
- t
->g
.max
.x
;
296 new_off_y
= t
->g
.normal
.y
- t
->g
.max
.y
;
297 t
->g
.max_offset
.x
+= new_off_x
- off_x
;
298 t
->g
.max_offset
.y
+= new_off_y
- off_y
;
300 if (flags
->do_update_title_dir
)
304 t
->hints
.win_gravity
, &t
->g
.max
, dw
,
306 gravity_constrain_size(
307 t
->hints
.win_gravity
, t
, &t
->g
.max
,
308 CS_UPDATE_MAX_DEFECT
);
314 new_g
= &t
->g
.normal
;
318 get_unshaded_geometry(t
, new_g
);
319 if (USED_TITLE_DIR_FOR_SHADING(t
))
321 SET_SHADED_DIR(t
, GET_TITLE_DIR(t
));
323 get_shaded_geometry(t
, &frame_g
, new_g
);
327 get_relative_geometry(&frame_g
, new_g
);
329 flags
->do_setup_frame
= True
;
330 flags
->do_redraw_decoration
= True
;
332 if (flags
->do_update_rotated_title
)
334 if (t
->title_text_rotation
!= ROTATION_0
)
336 flags
->do_setup_frame
= True
;
337 flags
->do_redraw_decoration
= True
;
340 if (flags
->do_resize_window
)
344 setup_frame_size_limits(t
, pstyle
);
346 frame_g
= t
->g
.normal
;
347 gravity_constrain_size(t
->hints
.win_gravity
, t
, &frame_g
, 0);
348 t
->g
.normal
= frame_g
;
352 gravity_constrain_size(
353 t
->hints
.win_gravity
, t
, &frame_g
,
354 CS_UPDATE_MAX_DEFECT
);
358 gravity_constrain_size(
359 t
->hints
.win_gravity
, t
, &frame_g
, 0);
361 flags
->do_setup_frame
= True
;
362 flags
->do_redraw_decoration
= True
;
364 if (flags
->do_setup_frame
)
368 setup_title_geometry(t
, pstyle
);
369 /* frame_force_setup_window needs to know if the window is
371 tmp
= get_focus_window();
372 set_focus_window(focus_w
);
373 frame_force_setup_window(
374 t
, frame_g
.x
, frame_g
.y
, frame_g
.width
, frame_g
.height
,
376 set_focus_window(tmp
);
378 EWMH_SetFrameStrut(t
);
380 if (flags
->do_update_window_color
)
384 flags
->do_redraw_decoration
= True
;
386 update_window_color_style(t
, pstyle
);
389 flags
->do_broadcast_focus
= True
;
392 if (flags
->do_update_window_color_hi
)
396 flags
->do_redraw_decoration
= True
;
398 update_window_color_hi_style(t
, pstyle
);
399 flags
->do_broadcast_focus
= True
;
402 flags
->do_broadcast_focus
= True
;
405 if (flags
->do_update_icon_title_cs_hi
)
407 if (t
== focus_w
&& IS_ICONIFIED(t
))
409 flags
->do_redraw_icon
= True
;
411 update_icon_title_cs_hi_style(t
, pstyle
);
413 if (flags
->do_update_icon_title_cs
)
415 if (t
!= focus_w
&& IS_ICONIFIED(t
))
417 flags
->do_redraw_icon
= True
;
419 update_icon_title_cs_style(t
, pstyle
);
421 if (flags
->do_update_icon_background_cs
)
423 int old_cs
= t
->icon_background_cs
;
425 update_icon_background_cs_style(t
, pstyle
);
426 if ((old_cs
< 0 && t
->icon_background_cs
>= 0) ||
427 (old_cs
>= 0 && t
->icon_background_cs
< 0))
429 flags
->do_update_icon
= True
;
433 flags
->do_redraw_icon
= True
;
436 if (flags
->do_update_icon_size_limits
)
438 setup_icon_size_limits(t
, pstyle
);
439 flags
->do_update_icon
= True
;
441 if (flags
->do_update_icon_font
)
443 if (!is_style_initialised
)
445 init_style(&old_t
, t
, pstyle
, &buttons
);
446 is_style_initialised
= True
;
448 setup_icon_font(t
, pstyle
, flags
->do_update_icon_font
);
449 flags
->do_update_icon_title
= True
;
451 if (flags
->do_update_icon_boxes
)
453 change_icon_boxes(t
, pstyle
);
455 if (flags
->do_update_icon
)
457 setup_icon_background_parameters(t
, pstyle
);
458 setup_icon_title_parameters(t
, pstyle
);
459 change_icon(t
, pstyle
);
460 flags
->do_update_icon_placement
= True
;
461 flags
->do_update_icon_title
= False
;
462 flags
->do_redraw_icon
= False
;
463 flags
->do_update_ewmh_icon
= True
;
465 if (flags
->do_redraw_icon
)
467 /* should not test if the window is iconified */
468 DrawIconWindow(t
, True
, True
, False
, True
, NULL
);;
469 flags
->do_redraw_decoration
= False
;
470 flags
->do_update_icon_title
= False
;
472 if (flags
->do_update_icon_title
)
476 if (flags
->do_update_icon_placement
)
480 initial_window_options_t win_opts
;
482 memset(&win_opts
, 0, sizeof(win_opts
));
484 Iconify(t
, &win_opts
);
485 flags
->do_redraw_decoration
= False
;
488 if (flags
->do_redraw_decoration
)
492 /* frame_redraw_decorations needs to know if the window is
494 tmp
= get_focus_window();
495 set_focus_window(focus_w
);
498 DrawIconWindow(t
, True
, True
, False
, False
, NULL
);
502 border_redraw_decorations(t
);
504 set_focus_window(tmp
);
506 if (flags
->do_update_frame_attributes
)
508 setup_frame_attributes(t
, pstyle
);
510 if (flags
->do_update_ewmh_state_hints
)
512 EWMH_SetWMState(t
, False
);
514 if (flags
->do_update_modules_flags
)
516 BroadcastConfig(M_CONFIGURE_WINDOW
,t
);
518 if (flags
->do_update_ewmh_mini_icon
|| flags
->do_update_ewmh_icon
)
521 t
, flags
->do_update_ewmh_mini_icon
,
522 flags
->do_update_ewmh_icon
);
524 if (flags
->do_update_placement_penalty
)
526 setup_placement_penalty(t
, pstyle
);
528 if (flags
->do_update_working_area
)
530 EWMH_UpdateWorkArea();
532 if (flags
->do_update_ewmh_stacking_hints
)
534 if (DO_EWMH_USE_STACKING_HINTS(t
))
536 if (t
->ewmh_hint_layer
> 0 &&
537 t
->layer
!= t
->ewmh_hint_layer
)
539 t
->ewmh_normal_layer
= t
->layer
;
540 new_layer(t
, t
->ewmh_hint_layer
);
545 if (t
->ewmh_hint_layer
> 0 && t
->ewmh_normal_layer
)
547 if (t
->ewmh_normal_layer
)
549 new_layer(t
, t
->ewmh_normal_layer
);
553 new_layer(t
, Scr
.DefaultLayer
);
558 if (flags
->do_update_ewmh_allowed_actions
)
560 EWMH_SetAllowedActions(t
);
562 if (flags
->do_broadcast_focus
)
564 if (Scr
.Hilite
!= NULL
&& t
== Scr
.Hilite
)
567 M_FOCUS_CHANGE
, 5, (long)FW_W(Scr
.Hilite
),
568 (long)FW_W_FRAME(Scr
.Hilite
), (long)0,
569 (long)Scr
.Hilite
->hicolors
.fore
,
570 (long)Scr
.Hilite
->hicolors
.back
);
573 if (flags
->do_refresh
)
575 if (!IS_ICONIFIED(t
))
577 refresh_window(FW_W_FRAME(t
), False
);
580 setup_numeric_vals(t
, pstyle
);
581 if (flags
->do_update_cr_motion_method
)
583 switch (SCR_MOTION_METHOD(&pstyle
->flags
))
585 case WS_CR_MOTION_METHOD_AUTO
:
586 if (WAS_CR_MOTION_METHOD_DETECTED(t
))
588 /* method was already detected, keep it */
592 case WS_CR_MOTION_METHOD_USE_GRAV
:
593 case WS_CR_MOTION_METHOD_STATIC_GRAV
:
594 SET_CR_MOTION_METHOD(
595 t
, SCR_MOTION_METHOD(&pstyle
->flags
));
596 SET_CR_MOTION_METHOD_DETECTED(t
, 0);
601 if (flags
->do_update_layer
)
603 int layer
= get_layer(t
);
605 if (SUSE_LAYER(&pstyle
->flags
))
607 /* use layer from style */
608 layer
= SGET_LAYER(*pstyle
);
611 /* Set the layer, and modify the stack ring. */
618 /* ---------------------------- builtin commands --------------------------- */
620 /* takes only care of destroying windows that have to go away. */
621 void destroy_scheduled_windows(void)
624 Bool do_need_ungrab
= False
;
626 if (Scr
.flags
.is_executing_complex_function
||
627 Scr
.flags
.is_executing_menu_function
||
628 !Scr
.flags
.is_window_scheduled_for_destroy
)
632 /* Grab the server during the style update! */
633 if (GrabEm(CRS_WAIT
, GRAB_BUSY
))
635 do_need_ungrab
= True
;
638 Scr
.flags
.is_window_scheduled_for_destroy
= 0;
639 /* need to destroy one or more windows before looking at the window
641 for (t
= Scr
.FWScheduledForDestroy
; t
!= NULL
; t
= t
->next
)
643 destroy_window(t
->object
);
645 Scr
.FWScheduledForDestroy
= flist_free_list(Scr
.FWScheduledForDestroy
);
646 MyXUngrabServer(dpy
);
655 /* similar to the flush_window_updates() function, but does only the updates
656 * for a single window whose decor has been changed. */
657 void apply_decor_change(FvwmWindow
*fw
)
662 lookup_style(fw
, &style
);
663 memset(&flags
, 0, sizeof(flags
));
664 flags
.do_redecorate
= True
;
665 flags
.do_update_window_font_height
= True
;
666 apply_window_updates(fw
, &flags
, &style
, get_focus_window());
671 /* Check and apply new style to each window if the style has changed. */
672 void flush_window_updates(void)
676 FvwmWindow
*focus_fw
;
677 Bool do_need_ungrab
= False
;
680 /* Grab the server during the style update! */
681 if (GrabEm(CRS_WAIT
, GRAB_BUSY
))
683 do_need_ungrab
= True
;
687 /* This is necessary in case the focus policy changes. With
688 * ClickToFocus some buttons have to be grabbed/ungrabbed. */
689 focus_fw
= get_focus_window();
692 /* Apply the new default font and colours first */
693 if (Scr
.flags
.has_default_color_changed
||
694 Scr
.flags
.has_default_font_changed
)
696 ApplyDefaultFontAndColors();
699 /* update styles for all windows */
700 for (t
= Scr
.FvwmRoot
.next
; t
!= NULL
; t
= t
->next
)
702 memset(&flags
, 0, sizeof(update_win
));
703 check_window_style_change(t
, &flags
, &style
);
704 if (Scr
.flags
.has_xinerama_state_changed
)
706 flags
.do_update_icon_boxes
= True
;
707 flags
.do_update_icon_placement
= True
;
709 if (Scr
.flags
.has_nr_buttons_changed
)
711 flags
.do_redecorate
= True
;
713 /* TODO: this is not optimised for minimal redrawing yet*/
714 if (t
->decor
->flags
.has_changed
)
716 flags
.do_redecorate
= True
;
717 flags
.do_update_window_font_height
= True
;
719 if (Scr
.flags
.has_default_font_changed
&& !HAS_ICON_FONT(t
))
721 flags
.do_update_icon_font
= True
;
723 if (Scr
.flags
.has_default_font_changed
&& !HAS_WINDOW_FONT(t
))
725 flags
.do_update_window_font
= True
;
727 if (t
->decor
->flags
.has_title_height_changed
)
729 flags
.do_update_window_font_height
= True
;
731 if (Scr
.flags
.has_mouse_binding_changed
)
733 flags
.do_update_window_grabs
= True
;
735 /* now apply the changes */
736 apply_window_updates(t
, &flags
, &style
, focus_fw
);
739 /* restore the focus; also handles the case that the previously focused
740 * window is now NeverFocus */
743 SetFocusWindow(focus_fw
, False
, FOCUS_SET_FORCE
);
744 if (Scr
.flags
.has_mouse_binding_changed
)
746 focus_grab_buttons(focus_fw
);
754 /* finally clean up the change flags */
755 reset_style_changes();
756 reset_decor_changes();
757 Scr
.flags
.do_need_window_update
= 0;
758 Scr
.flags
.has_default_font_changed
= 0;
759 Scr
.flags
.has_default_color_changed
= 0;
760 Scr
.flags
.has_mouse_binding_changed
= 0;
761 Scr
.flags
.has_nr_buttons_changed
= 0;
762 Scr
.flags
.has_xinerama_state_changed
= 0;
764 MyXUngrabServer(dpy
);
773 void CMD_UpdateStyles(F_CMD_ARGS
)
775 if (Scr
.flags
.do_need_window_update
)
777 flush_window_updates();