all repos — openbox @ 515f8d8760f614b127b4435dca7881a32b5b6207

openbox fork - make it a bit more like ryudo

plugins/focus.c (raw)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include "../kernel/dispatch.h"
#include "../kernel/screen.h"
#include "../kernel/client.h"
#include "../kernel/focus.h"
#include "../kernel/stacking.h"
#include "../kernel/openbox.h"

static int skip_enter = 0;

static void focus_fallback(guint desk, gboolean warp)
{
    GList *it;

    for (it = focus_order[desk]; it != NULL; it = it->next)
        if (client_focus(it->data)) {
            if (warp) { /* XXX make this configurable */
                XEvent e;
                Client *c = it->data;

                /* skip the next enter event from the desktop switch so focus
                   doesn't skip briefly to what was under the pointer */
                if (XCheckTypedEvent(ob_display, EnterNotify, &e)) {
                    XPutBackEvent(ob_display, &e);
                    /* XXX WERE NOT SKIPPING THEM ALL@&*)! */
                    g_message("Skip");
                    ++skip_enter;
                }

                /* I have to do this warp twice! Otherwise windows dont get
                   Enter/Leave events when i warp on a desktop switch! */
                XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
                             c->area.width / 2, c->area.height / 2);
                XWarpPointer(ob_display, None, c->window, 0, 0, 0, 0,
                             c->area.width / 2, c->area.height / 2);
            }
            break;
        }
}

static void events(ObEvent *e, void *foo)
{
    switch (e->type) {
    case Event_Client_Mapped:
        /* focus new normal windows */
        if (client_normal(e->data.c.client))
            client_focus(e->data.c.client);
        break;

    case Event_Ob_Desktop:
        /* focus the next available target */
        focus_fallback(e->data.o.num[0], TRUE);
        break;

    case Event_Client_Unfocus:
        /* dont do this shit with sloppy focus... */
        /*
        /\* nothing is left with focus! *\/
        if (focus_client == NULL) 
            /\* focus the next available target *\/
            focus_fallback(screen_desktop, FALSE);
        */
        break;

    case Event_X_EnterNotify:
        if (skip_enter)
            --skip_enter;
        else if (e->data.x.client && client_normal(e->data.x.client))
            client_focus(e->data.x.client);
        break;

    default:
        g_assert_not_reached();
    }
}

void plugin_startup()
{
    dispatch_register(Event_Client_Mapped | 
                      Event_Ob_Desktop | 
                      Event_Client_Unfocus |
                      Event_X_EnterNotify,
                      (EventHandler)events, NULL);
}

void plugin_shutdown()
{
    dispatch_register(0, (EventHandler)events, NULL);
}