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 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
);
111 !fpol_query_allow_user_focus(&FW_FOCUS_POLICY(t
)))
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
;
142 * These are a bit complicated because they can move windows to a
143 * different page or desk. */
144 ecc
.type
= EXCT_NULL
;
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 */
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
)
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
);
181 if (EWMH_SetIconFromWMIcon(t
, NULL
, 0, True
))
183 SET_HAS_EWMH_MINI_ICON(t
, True
);
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
)
232 if (flags
->do_redecorate
)
234 if (!is_style_initialised
)
236 init_style(&old_t
, t
, pstyle
, &buttons
);
237 is_style_initialised
= True
;
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
,
248 /* gravity without decor */
249 gravity_translate_to_northwest_geometry_no_bw(
250 old_t
.hints
.win_gravity
, &old_t
, &naked_g
,
252 /* set g.normal with the decor */
253 gravity_add_decoration(
254 old_t
.hints
.win_gravity
, t
, &t
->g
.normal
,
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
);
266 dw
= b_new
.total_size
.width
- b_old
.total_size
.width
;
267 dh
= b_new
.total_size
.height
- b_old
.total_size
.height
;
269 t
->hints
.win_gravity
, &t
->g
.normal
, dw
, dh
);
270 gravity_constrain_size(
271 t
->hints
.win_gravity
, t
, &t
->g
.normal
, 0);
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
;
283 /* maximized windows are always considered to
284 * have NorthWestGravity */
285 gravity_get_naked_geometry(
286 NorthWestGravity
, &old_t
, &naked_g
,
288 gravity_translate_to_northwest_geometry_no_bw(
289 NorthWestGravity
, &old_t
, &naked_g
,
291 gravity_add_decoration(
292 NorthWestGravity
, t
, &t
->g
.max
,
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
)
305 t
->hints
.win_gravity
, &t
->g
.max
, dw
,
307 gravity_constrain_size(
308 t
->hints
.win_gravity
, t
, &t
->g
.max
,
309 CS_UPDATE_MAX_DEFECT
);
315 new_g
= &t
->g
.normal
;
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
);
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
)
345 setup_frame_size_limits(t
, pstyle
);
347 frame_g
= t
->g
.normal
;
348 gravity_constrain_size(t
->hints
.win_gravity
, t
, &frame_g
, 0);
349 t
->g
.normal
= frame_g
;
353 gravity_constrain_size(
354 t
->hints
.win_gravity
, t
, &frame_g
,
355 CS_UPDATE_MAX_DEFECT
);
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
)
369 setup_title_geometry(t
, pstyle
);
370 /* frame_force_setup_window needs to know if the window is
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
,
377 set_focus_window(tmp
);
379 EWMH_SetFrameStrut(t
);
381 if (flags
->do_update_window_color
)
385 flags
->do_redraw_decoration
= True
;
387 update_window_color_style(t
, pstyle
);
390 flags
->do_broadcast_focus
= True
;
393 if (flags
->do_update_window_color_hi
)
397 flags
->do_redraw_decoration
= True
;
399 update_window_color_hi_style(t
, pstyle
);
400 flags
->do_broadcast_focus
= True
;
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
;
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
)
477 if (flags
->do_update_icon_placement
)
481 initial_window_options_t win_opts
;
483 memset(&win_opts
, 0, sizeof(win_opts
));
485 Iconify(t
, &win_opts
);
486 flags
->do_redraw_decoration
= False
;
489 if (flags
->do_redraw_decoration
)
493 /* frame_redraw_decorations needs to know if the window is
495 tmp
= get_focus_window();
496 set_focus_window(focus_w
);
499 DrawIconWindow(t
, True
, True
, False
, False
, NULL
);
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
)
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
);
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
);
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
)
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 */
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);
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. */
619 /* ---------------------------- builtin commands --------------------------- */
621 /* takes only care of destroying windows that have to go away. */
622 void destroy_scheduled_windows(void)
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
)
633 /* Grab the server during the style update! */
634 if (GrabEm(CRS_WAIT
, GRAB_BUSY
))
636 do_need_ungrab
= True
;
639 Scr
.flags
.is_window_scheduled_for_destroy
= 0;
640 /* need to destroy one or more windows before looking at the window
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
);
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
)
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());
672 /* Check and apply new style to each window if the style has changed. */
673 void flush_window_updates(void)
677 FvwmWindow
*focus_fw
;
678 Bool do_need_ungrab
= False
;
681 /* Grab the server during the style update! */
682 if (GrabEm(CRS_WAIT
, GRAB_BUSY
))
684 do_need_ungrab
= True
;
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();
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 */
744 SetFocusWindow(focus_fw
, False
, FOCUS_SET_FORCE
);
745 if (Scr
.flags
.has_mouse_binding_changed
)
747 focus_grab_buttons(focus_fw
);
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
);
774 void CMD_UpdateStyles(F_CMD_ARGS
)
776 if (Scr
.flags
.do_need_window_update
)
778 flush_window_updates();