4 #include "framerender.h"
19 Client
*focus_client
= NULL
;
20 GList
**focus_order
= NULL
; /* these lists are created when screen_startup
21 sets the number of desktops */
23 Window focus_backup
= None
;
25 static Client
*focus_cycle_target
= NULL
;
29 /* create the window which gets focus when no clients get it. Have to
30 make it override-redirect so we don't try manage it, since it is
32 XSetWindowAttributes attrib
;
36 attrib
.override_redirect
= TRUE
;
37 focus_backup
= XCreateWindow(ob_display
, ob_root
,
39 CopyFromParent
, InputOutput
, CopyFromParent
,
40 CWOverrideRedirect
, &attrib
);
41 XMapWindow(ob_display
, focus_backup
);
42 stacking_raise_internal(focus_backup
);
44 /* start with nothing focused */
45 focus_set_client(NULL
);
52 for (i
= 0; i
< screen_num_desktops
; ++i
)
53 g_list_free(focus_order
[i
]);
57 XDestroyWindow(ob_display
, focus_backup
);
59 /* reset focus to root */
60 XSetInputFocus(ob_display
, PointerRoot
, RevertToPointerRoot
,
64 static void push_to_top(Client
*client
)
68 desktop
= client
->desktop
;
69 if (desktop
== DESKTOP_ALL
) desktop
= screen_desktop
;
70 focus_order
[desktop
] = g_list_remove(focus_order
[desktop
], client
);
71 focus_order
[desktop
] = g_list_prepend(focus_order
[desktop
], client
);
74 void focus_set_client(Client
*client
)
79 /* uninstall the old colormap, and install the new one */
80 screen_install_colormap(focus_client
, FALSE
);
81 screen_install_colormap(client
, TRUE
);
84 /* when nothing will be focused, send focus to the backup target */
85 XSetInputFocus(ob_display
, focus_backup
, RevertToPointerRoot
,
87 XSync(ob_display
, FALSE
);
90 /* in the middle of cycling..? kill it. */
91 if (focus_cycle_target
)
92 focus_cycle(TRUE
, TRUE
, TRUE
, TRUE
);
95 focus_client
= client
;
97 /* move to the top of the list */
101 /* set the NET_ACTIVE_WINDOW hint */
102 active
= client
? client
->window
: None
;
103 PROP_SET32(ob_root
, net_active_window
, window
, active
);
105 if (focus_client
!= NULL
)
106 dispatch_client(Event_Client_Focus
, focus_client
, 0, 0);
108 dispatch_client(Event_Client_Unfocus
, old
, 0, 0);
111 static gboolean
focus_under_pointer()
116 if (ob_pointer_pos(&x
, &y
)) {
117 for (it
= stacking_list
; it
!= NULL
; it
= it
->next
) {
118 Client
*c
= it
->data
;
119 if (c
->desktop
== screen_desktop
&&
120 RECT_CONTAINS(c
->frame
->area
, x
, y
))
124 return client_normal(it
->data
) && client_focus(it
->data
);
129 /* finds the first transient that isn't 'skip' and ensure's that client_normal
131 static Client
*find_transient_recursive(Client
*c
, Client
*top
, Client
*skip
)
136 for (it
= c
->transients
; it
; it
= it
->next
) {
137 if (it
->data
== top
) return NULL
;
138 ret
= find_transient_recursive(it
->data
, top
, skip
);
139 if (ret
&& ret
!= skip
&& client_normal(ret
)) return ret
;
140 if (it
->data
!= skip
&& client_normal(it
->data
)) return it
->data
;
145 static gboolean
focus_fallback_transient(Client
*top
, Client
*old
)
147 Client
*target
= find_transient_recursive(top
, top
, old
);
149 /* make sure client_normal is true always */
150 if (!client_normal(top
))
152 target
= top
; /* no transient, keep the top */
154 return client_focus(target
);
157 void focus_fallback(FallbackType type
)
164 /* unfocus any focused clients.. they can be focused by Pointer events
165 and such, and then when I try focus them, I won't get a FocusIn event
168 focus_set_client(NULL
);
170 if (!(type
== Fallback_Desktop
?
171 config_focus_last_on_desktop
: config_focus_last
)) {
172 if (config_focus_follow
) focus_under_pointer();
176 if (type
== Fallback_Unfocusing
&& old
) {
177 /* try for transient relations */
178 if (old
->transient_for
) {
179 if (old
->transient_for
== TRAN_GROUP
) {
180 for (it
= focus_order
[screen_desktop
]; it
; it
= it
->next
) {
183 for (sit
= old
->group
->members
; sit
; sit
= sit
->next
)
184 if (sit
->data
== it
->data
)
185 if (focus_fallback_transient(sit
->data
, old
))
189 if (focus_fallback_transient(old
->transient_for
, old
))
194 /* try for group relations */
198 for (it
= focus_order
[screen_desktop
]; it
!= NULL
; it
= it
->next
)
199 for (sit
= old
->group
->members
; sit
; sit
= sit
->next
)
200 if (sit
->data
== it
->data
)
201 if (sit
->data
!= old
&& client_normal(sit
->data
))
202 if (client_focus(sit
->data
))
207 for (it
= focus_order
[screen_desktop
]; it
!= NULL
; it
= it
->next
)
208 if (type
!= Fallback_Unfocusing
|| it
->data
!= old
)
209 if (client_normal(it
->data
) && client_focus(it
->data
))
212 /* nothing to focus */
213 focus_set_client(NULL
);
216 static void popup_cycle(Client
*c
, gboolean show
)
218 XSetWindowAttributes attrib
;
219 static Window coords
= None
;
221 if (coords
== None
) {
222 attrib
.override_redirect
= TRUE
;
223 coords
= XCreateWindow(ob_display
, ob_root
,
224 0, 0, 1, 1, 0, render_depth
, InputOutput
,
225 render_visual
, CWOverrideRedirect
, &attrib
);
226 g_assert(coords
!= None
);
228 grab_pointer(TRUE
, None
);
230 XMapWindow(ob_display
, coords
);
234 XDestroyWindow(ob_display
, coords
);
237 grab_pointer(FALSE
, None
);
242 a
= screen_area(c
->desktop
);
244 framerender_size_popup_label(c
->title
, &s
);
245 XMoveResizeWindow(ob_display
, coords
,
246 a
->x
+ (a
->width
- s
.width
) / 2,
247 a
->y
+ (a
->height
- s
.height
) / 2,
249 framerender_popup_label(coords
, &s
, c
->title
);
253 Client
*focus_cycle(gboolean forward
, gboolean linear
, gboolean done
,
256 static Client
*first
= NULL
;
257 static Client
*t
= NULL
;
258 static GList
*order
= NULL
;
259 GList
*it
, *start
, *list
;
263 /*if (first) client_focus(first); XXX*/
264 if (focus_cycle_target
)
265 frame_adjust_focus(focus_cycle_target
->frame
, FALSE
);
267 frame_adjust_focus(focus_client
->frame
, TRUE
);
270 if (focus_cycle_target
) {
271 if (focus_cycle_target
->iconic
)
272 client_iconify(focus_cycle_target
, FALSE
, FALSE
);
273 client_focus(focus_cycle_target
);
274 stacking_raise(focus_cycle_target
);
278 if (!first
) first
= focus_client
;
279 if (!focus_cycle_target
) focus_cycle_target
= focus_client
;
281 if (linear
) list
= client_list
;
282 else list
= focus_order
[screen_desktop
];
284 start
= it
= g_list_find(list
, focus_cycle_target
);
285 if (!start
) /* switched desktops or something? */
286 start
= it
= forward
? g_list_last(list
) : g_list_first(list
);
287 if (!start
) goto done_cycle
;
292 if (it
== NULL
) it
= g_list_first(list
);
295 if (it
== NULL
) it
= g_list_last(list
);
297 ft
= client_focus_target(it
->data
);
298 if (ft
== it
->data
&& client_normal(ft
) &&
299 (ft
->can_focus
|| ft
->focus_notify
) &&
300 (ft
->desktop
== screen_desktop
|| ft
->desktop
== DESKTOP_ALL
)) {
301 if (focus_cycle_target
)
302 frame_adjust_focus(focus_cycle_target
->frame
, FALSE
);
303 focus_cycle_target
= ft
;
304 frame_adjust_focus(focus_cycle_target
->frame
, TRUE
);
305 popup_cycle(ft
, TRUE
);
308 } while (it
!= start
);
313 focus_cycle_target
= NULL
;
316 popup_cycle(ft
, FALSE
);
320 void focus_order_add_new(Client
*c
)
325 focus_order_to_top(c
);
328 if (d
== DESKTOP_ALL
) {
329 for (i
= 0; i
< screen_num_desktops
; ++i
) {
330 if (focus_order
[i
] && ((Client
*)focus_order
[i
]->data
)->iconic
)
331 focus_order
[i
] = g_list_insert(focus_order
[i
], c
, 0);
333 focus_order
[i
] = g_list_insert(focus_order
[i
], c
, 1);
336 if (focus_order
[d
] && ((Client
*)focus_order
[d
]->data
)->iconic
)
337 focus_order
[d
] = g_list_insert(focus_order
[d
], c
, 0);
339 focus_order
[d
] = g_list_insert(focus_order
[d
], c
, 1);
343 void focus_order_remove(Client
*c
)
348 if (d
== DESKTOP_ALL
) {
349 for (i
= 0; i
< screen_num_desktops
; ++i
)
350 focus_order
[i
] = g_list_remove(focus_order
[i
], c
);
352 focus_order
[d
] = g_list_remove(focus_order
[d
], c
);
355 static void to_top(Client
*c
, guint d
)
357 focus_order
[d
] = g_list_remove(focus_order
[d
], c
);
359 focus_order
[d
] = g_list_prepend(focus_order
[d
], c
);
363 /* insert before first iconic window */
364 for (it
= focus_order
[d
];
365 it
&& !((Client
*)it
->data
)->iconic
; it
= it
->next
);
366 g_list_insert_before(focus_order
[d
], it
, c
);
370 void focus_order_to_top(Client
*c
)
375 if (d
== DESKTOP_ALL
) {
376 for (i
= 0; i
< screen_num_desktops
; ++i
)
382 static void to_bottom(Client
*c
, guint d
)
384 focus_order
[d
] = g_list_remove(focus_order
[d
], c
);
386 focus_order
[d
] = g_list_append(focus_order
[d
], c
);
390 /* insert before first iconic window */
391 for (it
= focus_order
[d
];
392 it
&& !((Client
*)it
->data
)->iconic
; it
= it
->next
);
393 g_list_insert_before(focus_order
[d
], it
, c
);
397 void focus_order_to_bottom(Client
*c
)
402 if (d
== DESKTOP_ALL
) {
403 for (i
= 0; i
< screen_num_desktops
; ++i
)