1 /* -*- indent-tabs-mode: nil; tab-width: 4; c-basic-offset: 4; -*-
3 focus_cycle_popup.c for the Openbox window manager
4 Copyright (c) 2006 Mikael Magnusson
5 Copyright (c) 2003-2007 Dana Jansens
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 See the COPYING file for a copy of the GNU General Public License.
20 #include "focus_cycle_popup.h"
21 #include "focus_cycle.h"
30 #include "obrender/render.h"
35 /* Size of the icons, which can appear inside or outside of a hilite box */
36 #define ICON_SIZE (gint)config_theme_window_list_icon_size
37 /* Size of the hilite box around a window's icon */
38 #define HILITE_SIZE (ICON_SIZE + 2*HILITE_OFFSET)
39 /* Width of the outer ring around the hilite box */
40 #define HILITE_WIDTH 2
41 /* Space between the outer ring around the hilite box and the icon inside it */
42 #define HILITE_MARGIN 1
43 /* Total distance from the edge of the hilite box to the icon inside it */
44 #define HILITE_OFFSET (HILITE_WIDTH + HILITE_MARGIN)
45 /* Margin area around the outside of the dialog */
46 #define OUTSIDE_BORDER 3
47 /* Margin area around the text */
49 /* Scroll the list-mode list when the cursor gets within this many rows of the
51 #define SCROLL_MARGIN 4
53 typedef struct _ObFocusCyclePopup ObFocusCyclePopup
;
54 typedef struct _ObFocusCyclePopupTarget ObFocusCyclePopupTarget
;
56 struct _ObFocusCyclePopupTarget
62 /* This is used when the popup is in list mode */
66 struct _ObFocusCyclePopup
71 /* This is used when the popup is in icon mode */
72 Window icon_mode_text
;
75 Window list_mode_down
;
80 const ObFocusCyclePopupTarget
*last_target
;
84 /* How are the list is scrolled, in scroll mode */
89 RrAppearance
*a_hilite_text
;
91 RrAppearance
*a_arrow
;
94 ObFocusCyclePopupMode mode
;
97 /*! This popup shows all possible windows */
98 static ObFocusCyclePopup popup
;
99 /*! This popup shows a single window */
100 static ObIconPopup
*single_popup
;
102 static gchar
*popup_get_name (ObClient
*c
);
103 static gboolean
popup_setup (ObFocusCyclePopup
*p
,
104 gboolean create_targets
,
105 gboolean refresh_targets
);
106 static void popup_render (ObFocusCyclePopup
*p
,
109 static Window
create_window(Window parent
, guint bwidth
, gulong mask
,
110 XSetWindowAttributes
*attr
)
112 return XCreateWindow(obt_display
, parent
, 0, 0, 1, 1, bwidth
,
113 RrDepth(ob_rr_inst
), InputOutput
,
114 RrVisual(ob_rr_inst
), mask
, attr
);
117 void focus_cycle_popup_startup(gboolean reconfig
)
119 XSetWindowAttributes attrib
;
122 single_popup
= icon_popup_new();
124 popup
.obwin
.type
= OB_WINDOW_CLASS_INTERNAL
;
125 popup
.a_bg
= RrAppearanceCopy(ob_rr_theme
->osd_bg
);
126 popup
.a_hilite_text
= RrAppearanceCopy(ob_rr_theme
->osd_hilite_label
);
127 popup
.a_text
= RrAppearanceCopy(ob_rr_theme
->osd_unhilite_label
);
128 popup
.a_icon
= RrAppearanceCopy(ob_rr_theme
->a_clear
);
129 popup
.a_arrow
= RrAppearanceCopy(ob_rr_theme
->a_clear_tex
);
131 popup
.a_hilite_text
->surface
.parent
= popup
.a_bg
;
132 popup
.a_text
->surface
.parent
= popup
.a_bg
;
133 popup
.a_icon
->surface
.parent
= popup
.a_bg
;
135 popup
.a_text
->texture
[0].data
.text
.justify
= RR_JUSTIFY_LEFT
;
136 popup
.a_hilite_text
->texture
[0].data
.text
.justify
= RR_JUSTIFY_LEFT
;
138 /* 2 textures. texture[0] is the icon. texture[1] is the hilight, and
139 may or may not be used */
140 RrAppearanceAddTextures(popup
.a_icon
, 2);
142 RrAppearanceClearTextures(popup
.a_icon
);
143 popup
.a_icon
->texture
[0].type
= RR_TEXTURE_IMAGE
;
145 RrAppearanceClearTextures(popup
.a_arrow
);
146 popup
.a_arrow
->texture
[0].type
= RR_TEXTURE_MASK
;
147 popup
.a_arrow
->texture
[0].data
.mask
.color
=
148 ob_rr_theme
->osd_text_active_color
;
150 attrib
.override_redirect
= True
;
151 attrib
.border_pixel
=RrColorPixel(ob_rr_theme
->osd_border_color
);
152 popup
.bg
= create_window(obt_root(ob_screen
), ob_rr_theme
->obwidth
,
153 CWOverrideRedirect
| CWBorderPixel
, &attrib
);
155 /* create the text window used for the icon-mode popup */
156 popup
.icon_mode_text
= create_window(popup
.bg
, 0, 0, NULL
);
158 /* create the windows for the up and down arrows */
159 popup
.list_mode_up
= create_window(popup
.bg
, 0, 0, NULL
);
160 popup
.list_mode_down
= create_window(popup
.bg
, 0, 0, NULL
);
162 popup
.targets
= NULL
;
164 popup
.last_target
= NULL
;
166 /* set up the hilite texture for the icon */
167 popup
.a_icon
->texture
[1].data
.rgba
.width
= HILITE_SIZE
;
168 popup
.a_icon
->texture
[1].data
.rgba
.height
= HILITE_SIZE
;
169 popup
.a_icon
->texture
[1].data
.rgba
.alpha
= 0xff;
170 p
= g_new(RrPixel32
, HILITE_SIZE
* HILITE_SIZE
);
171 popup
.a_icon
->texture
[1].data
.rgba
.data
= p
;
173 /* create the hilite under the target icon */
179 tc
= ob_rr_theme
->osd_text_active_color
;
180 color
= ((tc
->r
& 0xff) << RrDefaultRedOffset
) +
181 ((tc
->g
& 0xff) << RrDefaultGreenOffset
) +
182 ((tc
->b
& 0xff) << RrDefaultBlueOffset
);
185 for (x
= 0; x
< HILITE_SIZE
; x
++)
186 for (y
= 0; y
< HILITE_SIZE
; y
++) {
189 if (x
< HILITE_WIDTH
||
190 x
>= HILITE_SIZE
- HILITE_WIDTH
||
192 y
>= HILITE_SIZE
- HILITE_WIDTH
)
194 /* the border of the target */
197 /* the background of the target */
201 p
[o
++] = color
+ (a
<< RrDefaultAlphaOffset
);
205 stacking_add(INTERNAL_AS_WINDOW(&popup
));
206 window_add(&popup
.bg
, INTERNAL_AS_WINDOW(&popup
));
209 void focus_cycle_popup_shutdown(gboolean reconfig
)
211 icon_popup_free(single_popup
);
213 window_remove(popup
.bg
);
214 stacking_remove(INTERNAL_AS_WINDOW(&popup
));
216 while(popup
.targets
) {
217 ObFocusCyclePopupTarget
*t
= popup
.targets
->data
;
219 RrImageUnref(t
->icon
);
221 XDestroyWindow(obt_display
, t
->iconwin
);
222 XDestroyWindow(obt_display
, t
->textwin
);
225 popup
.targets
= g_list_delete_link(popup
.targets
, popup
.targets
);
228 g_free(popup
.a_icon
->texture
[1].data
.rgba
.data
);
229 popup
.a_icon
->texture
[1].data
.rgba
.data
= NULL
;
231 XDestroyWindow(obt_display
, popup
.list_mode_up
);
232 XDestroyWindow(obt_display
, popup
.list_mode_down
);
233 XDestroyWindow(obt_display
, popup
.icon_mode_text
);
234 XDestroyWindow(obt_display
, popup
.bg
);
236 RrAppearanceFree(popup
.a_arrow
);
237 RrAppearanceFree(popup
.a_icon
);
238 RrAppearanceFree(popup
.a_hilite_text
);
239 RrAppearanceFree(popup
.a_text
);
240 RrAppearanceFree(popup
.a_bg
);
243 static void popup_target_free(ObFocusCyclePopupTarget
*t
)
245 RrImageUnref(t
->icon
);
247 XDestroyWindow(obt_display
, t
->iconwin
);
248 XDestroyWindow(obt_display
, t
->textwin
);
249 g_slice_free(ObFocusCyclePopupTarget
, t
);
252 static gboolean
popup_setup(ObFocusCyclePopup
*p
, gboolean create_targets
,
253 gboolean refresh_targets
)
257 GList
*rtargets
; /* old targets for refresh */
261 if (refresh_targets
) {
262 rtargets
= p
->targets
;
263 rtlast
= g_list_last(rtargets
);
269 rtargets
= rtlast
= NULL
;
273 g_assert(p
->targets
== NULL
);
274 g_assert(p
->n_targets
== 0);
276 /* make its width to be the width of all the possible titles */
278 /* build a list of all the valid focus targets and measure their strings,
282 for (it
= g_list_last(focus_order
); it
; it
= g_list_previous(it
)) {
283 ObClient
*ft
= it
->data
;
285 if (focus_cycle_valid(ft
)) {
288 /* reuse the target if possible during refresh */
289 for (rit
= rtlast
; rit
; rit
= g_list_previous(rit
)) {
290 ObFocusCyclePopupTarget
*t
= rit
->data
;
291 if (t
->client
== ft
) {
293 rtlast
= g_list_previous(rit
);
294 rtargets
= g_list_remove_link(rtargets
, rit
);
296 p
->targets
= g_list_concat(rit
, p
->targets
);
300 change
= TRUE
; /* order changed */
306 gchar
*text
= popup_get_name(ft
);
309 p
->a_text
->texture
[0].data
.text
.string
= text
;
310 maxwidth
= MAX(maxwidth
, RrMinWidth(p
->a_text
));
312 if (!create_targets
) {
315 ObFocusCyclePopupTarget
*t
=
316 g_slice_new(ObFocusCyclePopupTarget
);
320 t
->icon
= client_icon(t
->client
);
321 RrImageRef(t
->icon
); /* own the icon so it won't go away */
322 t
->iconwin
= create_window(p
->bg
, 0, 0, NULL
);
323 t
->textwin
= create_window(p
->bg
, 0, 0, NULL
);
325 p
->targets
= g_list_prepend(p
->targets
, t
);
328 change
= TRUE
; /* added a window */
335 change
= TRUE
; /* removed a window */
338 popup_target_free(rtargets
->data
);
339 rtargets
= g_list_delete_link(rtargets
, rtargets
);
345 /* don't shrink when refreshing */
346 p
->maxtextw
= MAX(p
->maxtextw
, maxwidth
);
348 p
->maxtextw
= maxwidth
;
353 static void popup_cleanup(void)
355 while(popup
.targets
) {
356 popup_target_free(popup
.targets
->data
);
357 popup
.targets
= g_list_delete_link(popup
.targets
, popup
.targets
);
360 popup
.last_target
= NULL
;
363 static gchar
*popup_get_name(ObClient
*c
)
367 const gchar
*desk
= NULL
;
370 /* find our highest direct parent */
371 p
= client_search_top_direct_parent(c
);
373 if (c
->desktop
!= DESKTOP_ALL
&& c
->desktop
!= screen_desktop
)
374 desk
= screen_desktop_names
[c
->desktop
];
376 title
= c
->iconic
? c
->icon_title
: c
->title
;
378 /* use the transient's parent's title/icon if we don't have one */
379 if (p
!= c
&& title
[0] == '\0')
380 title
= p
->iconic
? p
->icon_title
: p
->title
;
383 ret
= g_strdup_printf("%s [%s]", title
, desk
);
385 ret
= g_strdup(title
);
390 static void popup_render(ObFocusCyclePopup
*p
, const ObClient
*c
)
395 Rect
const *screen_area
= NULL
;
398 const ObFocusCyclePopupTarget
*newtarget
;
399 ObFocusCyclePopupMode mode
= p
->mode
;
406 /* vars for icon mode */
407 gint icon_mode_textx
;
408 gint icon_mode_texty
;
411 /* vars for list mode */
412 gint list_mode_icon_column_w
= HILITE_SIZE
+ OUTSIDE_BORDER
;
413 gint up_arrow_x
, down_arrow_x
;
414 gint up_arrow_y
, down_arrow_y
;
415 gboolean showing_arrows
= FALSE
;
417 g_assert(mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
||
418 mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
);
420 screen_area
= screen_physical_area_primary(FALSE
);
422 /* get the outside margins */
423 RrMargins(p
->a_bg
, &ml
, &mt
, &mr
, &mb
);
425 /* get our outside borders */
426 l
= ml
+ OUTSIDE_BORDER
;
427 r
= mr
+ OUTSIDE_BORDER
;
428 t
= mt
+ OUTSIDE_BORDER
;
429 b
= mb
+ OUTSIDE_BORDER
;
431 /* get the width from the text and keep it within limits */
432 w
= l
+ r
+ p
->maxtextw
;
433 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
434 /* when in list mode, there are icons down the side */
435 w
+= list_mode_icon_column_w
;
436 w
= MIN(w
, MAX(screen_area
->width
/3, POPUP_WIDTH
)); /* max width */
437 w
= MAX(w
, POPUP_WIDTH
); /* min width */
439 /* get the text height */
440 texth
= RrMinHeight(p
->a_hilite_text
);
441 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
442 texth
= MAX(MAX(texth
, RrMinHeight(p
->a_text
)), HILITE_SIZE
);
444 texth
+= TEXT_BORDER
* 2;
446 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
) {
447 /* how many icons will fit in that row? make the width fit that */
449 icons_per_row
= (w
+ HILITE_SIZE
- 1) / HILITE_SIZE
;
450 w
= icons_per_row
* HILITE_SIZE
+ l
+ r
;
452 /* how many rows do we need? */
453 icon_rows
= (p
->n_targets
-1) / icons_per_row
+ 1;
455 /* in list mode, there is one column of icons.. */
457 /* maximum is 80% of the screen height */
458 icon_rows
= MIN(p
->n_targets
,
459 (4*screen_area
->height
/5) /* 80% of the screen */
461 MAX(HILITE_SIZE
, texth
)); /* height of each row */
462 /* but make sure there is always one */
463 icon_rows
= MAX(icon_rows
, 1);
466 /* get the text width */
468 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
469 /* leave space on the side for the icons */
470 textw
-= list_mode_icon_column_w
;
473 /* reset the scrolling when the dialog is first shown */
476 /* find the height of the dialog */
477 h
= t
+ b
+ (icon_rows
* MAX(HILITE_SIZE
, texth
));
478 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
)
479 /* in icon mode the text sits below the icons, so make some space */
480 h
+= OUTSIDE_BORDER
+ texth
;
482 /* find the focused target */
484 for (i
= 0, it
= p
->targets
; it
; ++i
, it
= g_list_next(it
)) {
485 const ObFocusCyclePopupTarget
*target
= it
->data
;
486 if (target
->client
== c
) {
487 /* save the target */
493 g_assert(newtarget
!= NULL
);
495 /* scroll the list if needed */
496 last_scroll
= p
->scroll
;
497 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
) {
498 const gint top
= p
->scroll
+ SCROLL_MARGIN
;
499 const gint bottom
= p
->scroll
+ icon_rows
- SCROLL_MARGIN
;
500 const gint min_scroll
= 0;
501 const gint max_scroll
= p
->n_targets
- icon_rows
;
503 if (top
- selected_pos
>= 0) {
504 p
->scroll
-= top
- selected_pos
+ 1;
505 p
->scroll
= MAX(p
->scroll
, min_scroll
);
506 } else if (selected_pos
- bottom
>= 0) {
507 p
->scroll
+= selected_pos
- bottom
+ 1;
508 p
->scroll
= MIN(p
->scroll
, max_scroll
);
512 /* show the scroll arrows when appropriate */
513 if (p
->scroll
&& mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
) {
514 XMapWindow(obt_display
, p
->list_mode_up
);
515 showing_arrows
= TRUE
;
517 XUnmapWindow(obt_display
, p
->list_mode_up
);
519 if (p
->scroll
< p
->n_targets
- icon_rows
&&
520 mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
522 XMapWindow(obt_display
, p
->list_mode_down
);
523 showing_arrows
= TRUE
;
525 XUnmapWindow(obt_display
, p
->list_mode_down
);
527 /* make space for the arrows */
529 h
+= ob_rr_theme
->up_arrow_mask
->height
+ OUTSIDE_BORDER
530 + ob_rr_theme
->down_arrow_mask
->height
+ OUTSIDE_BORDER
;
532 /* center the icons if there is less than one row */
533 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
&& icon_rows
== 1)
534 icons_center_x
= (w
- p
->n_targets
* HILITE_SIZE
) / 2;
538 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
) {
539 /* get the position of the text */
541 icon_mode_texty
= h
- texth
- b
;
544 /* find the position for the popup (include the outer borders) */
545 x
= screen_area
->x
+ (screen_area
->width
-
546 (w
+ ob_rr_theme
->obwidth
* 2)) / 2;
547 y
= screen_area
->y
+ (screen_area
->height
-
548 (h
+ ob_rr_theme
->obwidth
* 2)) / 2;
551 /* position the background but don't draw it */
552 XMoveResizeWindow(obt_display
, p
->bg
, x
, y
, w
, h
);
554 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
) {
555 /* position the text */
556 XMoveResizeWindow(obt_display
, p
->icon_mode_text
,
557 icon_mode_textx
, icon_mode_texty
, textw
, texth
);
558 XMapWindow(obt_display
, popup
.icon_mode_text
);
560 XUnmapWindow(obt_display
, popup
.icon_mode_text
);
562 up_arrow_x
= (w
- ob_rr_theme
->up_arrow_mask
->width
) / 2;
565 down_arrow_x
= (w
- ob_rr_theme
->down_arrow_mask
->width
) / 2;
566 down_arrow_y
= h
- b
- ob_rr_theme
->down_arrow_mask
->height
;
568 /* position the arrows */
569 XMoveResizeWindow(obt_display
, p
->list_mode_up
,
570 up_arrow_x
, up_arrow_y
,
571 ob_rr_theme
->up_arrow_mask
->width
,
572 ob_rr_theme
->up_arrow_mask
->height
);
573 XMoveResizeWindow(obt_display
, p
->list_mode_down
,
574 down_arrow_x
, down_arrow_y
,
575 ob_rr_theme
->down_arrow_mask
->width
,
576 ob_rr_theme
->down_arrow_mask
->height
);
580 /* * * draw everything * * */
582 /* draw the background */
584 RrPaint(p
->a_bg
, p
->bg
, w
, h
);
586 /* draw the scroll arrows */
587 if (!p
->mapped
&& mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
) {
588 p
->a_arrow
->texture
[0].data
.mask
.mask
=
589 ob_rr_theme
->up_arrow_mask
;
590 p
->a_arrow
->surface
.parent
= p
->a_bg
;
591 p
->a_arrow
->surface
.parentx
= up_arrow_x
;
592 p
->a_arrow
->surface
.parenty
= up_arrow_y
;
593 RrPaint(p
->a_arrow
, p
->list_mode_up
,
594 ob_rr_theme
->up_arrow_mask
->width
,
595 ob_rr_theme
->up_arrow_mask
->height
);
597 p
->a_arrow
->texture
[0].data
.mask
.mask
=
598 ob_rr_theme
->down_arrow_mask
;
599 p
->a_arrow
->surface
.parent
= p
->a_bg
;
600 p
->a_arrow
->surface
.parentx
= down_arrow_x
;
601 p
->a_arrow
->surface
.parenty
= down_arrow_y
;
602 RrPaint(p
->a_arrow
, p
->list_mode_down
,
603 ob_rr_theme
->down_arrow_mask
->width
,
604 ob_rr_theme
->down_arrow_mask
->height
);
607 /* draw the icons and text */
608 for (i
= 0, it
= p
->targets
; it
; ++i
, it
= g_list_next(it
)) {
609 const ObFocusCyclePopupTarget
*target
= it
->data
;
611 /* have to redraw the targetted icon and last targetted icon
612 * to update the hilite */
613 if (!p
->mapped
|| newtarget
== target
|| p
->last_target
== target
||
614 last_scroll
!= p
->scroll
)
616 /* row and column start from 0 */
617 const gint row
= i
/ icons_per_row
- p
->scroll
;
618 const gint col
= i
% icons_per_row
;
620 gint list_mode_textx
, list_mode_texty
;
623 /* find the coordinates for the icon */
624 iconx
= icons_center_x
+ l
+ (col
* HILITE_SIZE
);
625 icony
= t
+ (showing_arrows
? ob_rr_theme
->up_arrow_mask
->height
628 + (row
* MAX(texth
, HILITE_SIZE
))
629 + MAX(texth
- HILITE_SIZE
, 0) / 2;
631 /* find the dimensions of the text box */
632 list_mode_textx
= iconx
+ HILITE_SIZE
+ TEXT_BORDER
;
633 list_mode_texty
= icony
;
635 /* position the icon */
636 XMoveResizeWindow(obt_display
, target
->iconwin
,
637 iconx
, icony
, HILITE_SIZE
, HILITE_SIZE
);
639 /* position the text */
640 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
641 XMoveResizeWindow(obt_display
, target
->textwin
,
642 list_mode_textx
, list_mode_texty
,
645 /* show/hide the right windows */
646 if (row
>= 0 && row
< icon_rows
) {
647 XMapWindow(obt_display
, target
->iconwin
);
648 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
649 XMapWindow(obt_display
, target
->textwin
);
651 XUnmapWindow(obt_display
, target
->textwin
);
653 XUnmapWindow(obt_display
, target
->textwin
);
654 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
)
655 XUnmapWindow(obt_display
, target
->iconwin
);
657 XMapWindow(obt_display
, target
->iconwin
);
660 /* get the icon from the client */
661 p
->a_icon
->texture
[0].data
.image
.twidth
= ICON_SIZE
;
662 p
->a_icon
->texture
[0].data
.image
.theight
= ICON_SIZE
;
663 p
->a_icon
->texture
[0].data
.image
.tx
= HILITE_OFFSET
;
664 p
->a_icon
->texture
[0].data
.image
.ty
= HILITE_OFFSET
;
665 p
->a_icon
->texture
[0].data
.image
.alpha
=
666 target
->client
->iconic
? OB_ICONIC_ALPHA
: 0xff;
667 p
->a_icon
->texture
[0].data
.image
.image
= target
->icon
;
669 /* Draw the hilite? */
670 p
->a_icon
->texture
[1].type
= (target
== newtarget
) ?
671 RR_TEXTURE_RGBA
: RR_TEXTURE_NONE
;
674 p
->a_icon
->surface
.parentx
= iconx
;
675 p
->a_icon
->surface
.parenty
= icony
;
676 RrPaint(p
->a_icon
, target
->iconwin
, HILITE_SIZE
, HILITE_SIZE
);
679 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_LIST
||
682 text
= (target
== newtarget
) ? p
->a_hilite_text
: p
->a_text
;
683 text
->texture
[0].data
.text
.string
= target
->text
;
684 text
->surface
.parentx
=
685 mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
?
686 icon_mode_textx
: list_mode_textx
;
687 text
->surface
.parenty
=
688 mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
?
689 icon_mode_texty
: list_mode_texty
;
691 (mode
== OB_FOCUS_CYCLE_POPUP_MODE_ICONS
?
692 p
->icon_mode_text
: target
->textwin
),
698 p
->last_target
= newtarget
;
703 void focus_cycle_popup_show(ObClient
*c
, gboolean iconic_windows
,
704 gboolean all_desktops
, gboolean dock_windows
,
705 gboolean desktop_windows
,
706 ObFocusCyclePopupMode mode
)
710 if (mode
== OB_FOCUS_CYCLE_POPUP_MODE_NONE
) {
711 focus_cycle_popup_hide();
715 /* do this stuff only when the dialog is first showing */
717 popup_setup(&popup
, TRUE
, FALSE
);
718 /* this is fixed once the dialog is shown */
721 g_assert(popup
.targets
!= NULL
);
723 popup_render(&popup
, c
);
726 /* show the dialog */
727 XMapWindow(obt_display
, popup
.bg
);
730 screen_hide_desktop_popup();
734 void focus_cycle_popup_hide(void)
738 ignore_start
= event_start_ignore_all_enters();
740 XUnmapWindow(obt_display
, popup
.bg
);
743 event_end_ignore_all_enters(ignore_start
);
745 popup
.mapped
= FALSE
;
750 void focus_cycle_popup_single_show(struct _ObClient
*c
,
751 gboolean iconic_windows
,
752 gboolean all_desktops
,
753 gboolean dock_windows
,
754 gboolean desktop_windows
)
760 /* do this stuff only when the dialog is first showing */
764 popup_setup(&popup
, FALSE
, FALSE
);
765 g_assert(popup
.targets
== NULL
);
767 /* position the popup */
768 a
= screen_physical_area_primary(FALSE
);
769 icon_popup_position(single_popup
, CenterGravity
,
770 a
->x
+ a
->width
/ 2, a
->y
+ a
->height
/ 2);
771 icon_popup_height(single_popup
, POPUP_HEIGHT
);
772 icon_popup_min_width(single_popup
, POPUP_WIDTH
);
773 icon_popup_max_width(single_popup
, MAX(a
->width
/3, POPUP_WIDTH
));
774 icon_popup_text_width(single_popup
, popup
.maxtextw
);
777 text
= popup_get_name(c
);
778 icon_popup_show(single_popup
, text
, client_icon(c
));
780 screen_hide_desktop_popup();
783 void focus_cycle_popup_single_hide(void)
785 icon_popup_hide(single_popup
);
788 gboolean
focus_cycle_popup_is_showing(ObClient
*c
)
793 for (it
= popup
.targets
; it
; it
= g_list_next(it
)) {
794 ObFocusCyclePopupTarget
*t
= it
->data
;
802 static ObClient
* popup_revert(ObClient
*target
)
806 for (it
= popup
.targets
; it
; it
= g_list_next(it
)) {
807 ObFocusCyclePopupTarget
*t
= it
->data
;
808 if (t
->client
== target
) {
809 /* move to a previous window if possible */
810 for (itt
= it
->prev
; itt
; itt
= g_list_previous(itt
)) {
811 ObFocusCyclePopupTarget
*t2
= itt
->data
;
812 if (focus_cycle_valid(t2
->client
))
816 /* otherwise move to a following window if possible */
817 for (itt
= it
->next
; itt
; itt
= g_list_next(itt
)) {
818 ObFocusCyclePopupTarget
*t2
= itt
->data
;
819 if (focus_cycle_valid(t2
->client
))
823 /* otherwise, we can't go anywhere there is nowhere valid to go */
830 ObClient
* focus_cycle_popup_refresh(ObClient
*target
,
833 if (!popup
.mapped
) return NULL
;
835 if (!focus_cycle_valid(target
))
836 target
= popup_revert(target
);
838 redraw
= popup_setup(&popup
, TRUE
, TRUE
) && redraw
;
840 if (!target
&& popup
.targets
)
841 target
= ((ObFocusCyclePopupTarget
*)popup
.targets
->data
)->client
;
843 if (target
&& redraw
) {
844 popup
.mapped
= FALSE
;
845 popup_render(&popup
, target
);