File: xembed.c

package info (click to toggle)
awesome 4.3-8.1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 6,468 kB
  • sloc: ansic: 14,508; sh: 526; makefile: 46
file content (153 lines) | stat: -rw-r--r-- 4,759 bytes parent folder | download | duplicates (4)
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
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*
 * common/xembed.c - XEMBED functions
 *
 * Copyright © 2007-2008 Julien Danjou <julien@danjou.info>
 * Copyright © 2004 Matthew Reppert
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */

#include "common/xembed.h"
#include "common/util.h"
#include "common/atoms.h"

/* I should really include the correct header instead... */
void luaA_systray_invalidate(void);

/** Send an XEMBED message to a window.
 * \param connection Connection to the X server.
 * \param towin Destination window
 * \param message The message.
 * \param d1 Element 3 of message.
 * \param d2 Element 4 of message.
 * \param d3 Element 5 of message.
 */
void
xembed_message_send(xcb_connection_t *connection, xcb_window_t towin,
                    xcb_timestamp_t timestamp, uint32_t message, uint32_t d1, uint32_t d2, uint32_t d3)
{
    xcb_client_message_event_t ev;

    p_clear(&ev, 1);
    ev.response_type = XCB_CLIENT_MESSAGE;
    ev.window = towin;
    ev.format = 32;
    ev.data.data32[0] = timestamp;
    ev.data.data32[1] = message;
    ev.data.data32[2] = d1;
    ev.data.data32[3] = d2;
    ev.data.data32[4] = d3;
    ev.type = _XEMBED;
    xcb_send_event(connection, false, towin, XCB_EVENT_MASK_NO_EVENT, (char *) &ev);
}

/** Deliver a request to get XEMBED info for a window.
 * \param connection The X connection.
 * \param win The window.
 * \return A cookie.
 */
xcb_get_property_cookie_t
xembed_info_get_unchecked(xcb_connection_t *connection, xcb_window_t win)
{
    return xcb_get_property_unchecked(connection, false, win, _XEMBED_INFO,
                                      XCB_GET_PROPERTY_TYPE_ANY, 0L, 2);
}

static bool
xembed_info_from_reply(xembed_info_t *info, xcb_get_property_reply_t *prop_r)
{
    uint32_t *data;

    if(!prop_r || !prop_r->value_len)
        return false;

    if(!(data = (uint32_t *) xcb_get_property_value(prop_r)))
        return false;

    info->version = data[0];
    info->flags = data[1] & XEMBED_INFO_FLAGS_ALL;

    return true;
}

/** Get the XEMBED info for a window.
 * \param connection The X connection.
 * \param cookie The cookie of the request.
 * \param info The xembed_info_t structure to fill.
 */
bool
xembed_info_get_reply(xcb_connection_t *connection,
                      xcb_get_property_cookie_t cookie,
                      xembed_info_t *info)
{
    xcb_get_property_reply_t *prop_r = xcb_get_property_reply(connection, cookie, NULL);
    bool ret = xembed_info_from_reply(info, prop_r);
    p_delete(&prop_r);
    return ret;
}

/** Get a XEMBED window from a xembed_window_t list.
 * \param list The xembed window list.
 * \param win The window to look for.
 * \return The xembed window if found, NULL otherwise.
 */
xembed_window_t *
xembed_getbywin(xembed_window_array_t *list, xcb_window_t win)
{
    for(int i = 0; i < list->len; i++)
        if(list->tab[i].win == win)
            return &list->tab[i];
    return NULL;
}

/** Update embedded window properties.
 * \param connection The X connection.
 * \param emwin The embedded window.
 * \param timestamp The timestamp.
 * \param reply The property reply to handle.
 */
void
xembed_property_update(xcb_connection_t *connection, xembed_window_t *emwin,
                       xcb_timestamp_t timestamp, xcb_get_property_reply_t *reply)
{
    int flags_changed;
    xembed_info_t info = { 0, 0 };

    xembed_info_from_reply(&info, reply);

    /* test if it changed */
    if(!(flags_changed = info.flags ^ emwin->info.flags))
        return;

    emwin->info.flags = info.flags;
    if(flags_changed & XEMBED_MAPPED)
    {
        if(info.flags & XEMBED_MAPPED)
        {
            xcb_map_window(connection, emwin->win);
            xembed_window_activate(connection, emwin->win, timestamp);
        }
        else
        {
            xcb_unmap_window(connection, emwin->win);
            xembed_window_deactivate(connection, emwin->win, timestamp);
            xembed_focus_out(connection, emwin->win, timestamp);
        }
        luaA_systray_invalidate();
    }
}

// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80