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
;
100 if (flags
->do_setup_focus_policy
)
102 setup_focus_policy(t
);
104 !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(t
)))
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
;
135 * These are a bit complicated because they can move windows to a
136 * different page or desk. */
137 ecc
.type
= EXCT_NULL
;
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 */
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
)
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
);
174 if (EWMH_SetIconFromWMIcon(t
, NULL
, 0, True
))
176 SET_HAS_EWMH_MINI_ICON(t
, True
);
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
)
225 if (flags
->do_redecorate
)
227 if (!is_style_initialised
)
229 init_style(&old_t
, t
, pstyle
, &buttons
);
230 is_style_initialised
= True
;
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
,
241 /* gravity without decor */
242 gravity_translate_to_northwest_geometry_no_bw(
243 old_t
.hints
.win_gravity
, &old_t
, &naked_g
,
245 /* set g.normal with the decor */
246 gravity_add_decoration(
247 old_t
.hints
.win_gravity
, t
, &t
->g
.normal
,
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
);
259 dw
= b_new
.total_size
.width
- b_old
.total_size
.width
;
260 dh
= b_new
.total_size
.height
- b_old
.total_size
.height
;
262 t
->hints
.win_gravity
, &t
->g
.normal
, dw
, dh
);
263 gravity_constrain_size(
264 t
->hints
.win_gravity
, t
, &t
->g
.normal
, 0);
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
;
276 /* maximized windows are always considered to
277 * have NorthWestGravity */
278 gravity_get_naked_geometry(
279 NorthWestGravity
, &old_t
, &naked_g
,
281 gravity_translate_to_northwest_geometry_no_bw(
282 NorthWestGravity
, &old_t
, &naked_g
,
284 gravity_add_decoration(
285 NorthWestGravity
, t
, &t
->g
.max
,
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
)
298 t
->hints
.win_gravity
, &t
->g
.max
, dw
,
300 gravity_constrain_size(
301 t
->hints
.win_gravity
, t
, &t
->g
.max
,
302 CS_UPDATE_MAX_DEFECT
);
308 new_g
= &t
->g
.normal
;
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
);
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
)
338 setup_frame_size_limits(t
, pstyle
);
340 frame_g
= t
->g
.normal
;
341 gravity_constrain_size(t
->hints
.win_gravity
, t
, &frame_g
, 0);
342 t
->g
.normal
= frame_g
;
346 gravity_constrain_size(
347 t
->hints
.win_gravity
, t
, &frame_g
,
348 CS_UPDATE_MAX_DEFECT
);
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
)
362 setup_title_geometry(t
, pstyle
);
363 /* frame_force_setup_window needs to know if the window is
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
,
370 set_focus_window(tmp
);
372 EWMH_SetFrameStrut(t
);
374 if (flags
->do_update_window_color
)
378 flags
->do_redraw_decoration
= True
;
380 update_window_color_style(t
, pstyle
);
383 flags
->do_broadcast_focus
= True
;
386 if (flags
->do_update_window_color_hi
)
390 flags
->do_redraw_decoration
= True
;
392 update_window_color_hi_style(t
, pstyle
);
393 flags
->do_broadcast_focus
= True
;
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
;
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
)
470 if (flags
->do_update_icon_placement
)
474 initial_window_options_t win_opts
;
476 memset(&win_opts
, 0, sizeof(win_opts
));
478 Iconify(t
, &win_opts
);
479 flags
->do_redraw_decoration
= False
;
482 if (flags
->do_redraw_decoration
)
486 /* frame_redraw_decorations needs to know if the window is
488 tmp
= get_focus_window();
489 set_focus_window(focus_w
);
492 DrawIconWindow(t
, True
, True
, False
, False
, NULL
);
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
)
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
);
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
);
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
)
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 */
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);
598 /* ---------------------------- builtin commands --------------------------- */
600 /* takes only care of destroying windows that have to go away. */
601 void destroy_scheduled_windows(void)
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
)
612 /* Grab the server during the style update! */
613 if (GrabEm(CRS_WAIT
, GRAB_BUSY
))
615 do_need_ungrab
= True
;
618 Scr
.flags
.is_window_scheduled_for_destroy
= 0;
619 /* need to destroy one or more windows before looking at the window
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
);
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
)
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());
651 /* Check and apply new style to each window if the style has changed. */
652 void flush_window_updates(void)
656 FvwmWindow
*focus_fw
;
657 Bool do_need_ungrab
= False
;
660 /* Grab the server during the style update! */
661 if (GrabEm(CRS_WAIT
, GRAB_BUSY
))
663 do_need_ungrab
= True
;
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();
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 */
723 SetFocusWindow(focus_fw
, False
, FOCUS_SET_FORCE
);
724 if (Scr
.flags
.has_mouse_binding_changed
)
726 focus_grab_buttons(focus_fw
);
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
);
753 void CMD_UpdateStyles(F_CMD_ARGS
)
755 if (Scr
.flags
.do_need_window_update
)
757 flush_window_updates();