awesome/common/xembed.c
Uli Schlachter ec076ca4bd Properly support the XEMBED_MAPPED bit
The XEmbed protocol defines a special property that defines if the embedded
window wants to be visible or not. Up to now, awesome always ignored this entry
and instead behaved as if the bit was set. This commit makes it properly respect
the bit.

Testing done: None. No idea how. Apparently nothing really uses this bit,
because we didn't get bug reports about it yet.

Signed-off-by: Uli Schlachter <psychon@znc.in>
2016-05-31 08:55:42 +02:00

151 lines
4.5 KiB
C

/*
* 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,
long message, long d1, long d2, long 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] = XCB_CURRENT_TIME;
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.
*/
void
xembed_property_update(xcb_connection_t *connection, xembed_window_t *emwin,
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);
}
else
{
xcb_unmap_window(connection, emwin->win);
xembed_window_deactivate(connection, emwin->win);
xembed_focus_out(connection, emwin->win);
}
luaA_systray_invalidate();
}
}
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80