2007-12-27 17:27:20 +01:00
|
|
|
/*
|
|
|
|
* ewmh.c - EWMH support functions
|
|
|
|
*
|
2009-01-02 11:58:52 +01:00
|
|
|
* Copyright © 2007-2009 Julien Danjou <julien@danjou.info>
|
2007-12-27 17:27:20 +01:00
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2014-03-30 20:07:48 +02:00
|
|
|
#include "ewmh.h"
|
|
|
|
#include "objects/client.h"
|
|
|
|
#include "objects/tag.h"
|
|
|
|
#include "common/atoms.h"
|
2015-11-07 11:48:10 +01:00
|
|
|
#include "xwindow.h"
|
2014-03-30 20:07:48 +02:00
|
|
|
|
2008-06-18 08:55:31 +02:00
|
|
|
#include <sys/types.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
#include <xcb/xcb.h>
|
|
|
|
#include <xcb/xcb_atom.h>
|
2007-12-27 17:27:20 +01:00
|
|
|
|
2007-12-28 18:31:31 +01:00
|
|
|
#define _NET_WM_STATE_REMOVE 0
|
|
|
|
#define _NET_WM_STATE_ADD 1
|
|
|
|
#define _NET_WM_STATE_TOGGLE 2
|
|
|
|
|
2009-10-08 14:08:22 +02:00
|
|
|
/** Update client EWMH hints.
|
2015-02-14 18:55:42 +01:00
|
|
|
* \param L The Lua VM state.
|
2009-10-08 14:08:22 +02:00
|
|
|
*/
|
|
|
|
static int
|
|
|
|
ewmh_client_update_hints(lua_State *L)
|
|
|
|
{
|
|
|
|
client_t *c = luaA_checkudata(L, 1, &client_class);
|
|
|
|
xcb_atom_t state[10]; /* number of defined state atoms */
|
|
|
|
int i = 0;
|
|
|
|
|
|
|
|
if(c->modal)
|
|
|
|
state[i++] = _NET_WM_STATE_MODAL;
|
|
|
|
if(c->fullscreen)
|
|
|
|
state[i++] = _NET_WM_STATE_FULLSCREEN;
|
|
|
|
if(c->maximized_vertical)
|
|
|
|
state[i++] = _NET_WM_STATE_MAXIMIZED_VERT;
|
|
|
|
if(c->maximized_horizontal)
|
|
|
|
state[i++] = _NET_WM_STATE_MAXIMIZED_HORZ;
|
|
|
|
if(c->sticky)
|
|
|
|
state[i++] = _NET_WM_STATE_STICKY;
|
|
|
|
if(c->skip_taskbar)
|
|
|
|
state[i++] = _NET_WM_STATE_SKIP_TASKBAR;
|
|
|
|
if(c->above)
|
|
|
|
state[i++] = _NET_WM_STATE_ABOVE;
|
|
|
|
if(c->below)
|
|
|
|
state[i++] = _NET_WM_STATE_BELOW;
|
|
|
|
if(c->minimized)
|
|
|
|
state[i++] = _NET_WM_STATE_HIDDEN;
|
|
|
|
if(c->urgent)
|
|
|
|
state[i++] = _NET_WM_STATE_DEMANDS_ATTENTION;
|
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
c->window, _NET_WM_STATE, XCB_ATOM_ATOM, 32, i, state);
|
2009-10-08 14:08:22 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-10-08 14:49:41 +02:00
|
|
|
static int
|
|
|
|
ewmh_update_net_active_window(lua_State *L)
|
|
|
|
{
|
|
|
|
xcb_window_t win;
|
|
|
|
|
2010-10-10 14:46:56 +02:00
|
|
|
if(globalconf.focus.client)
|
|
|
|
win = globalconf.focus.client->window;
|
2009-10-08 14:49:41 +02:00
|
|
|
else
|
|
|
|
win = XCB_NONE;
|
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-16 14:10:58 +02:00
|
|
|
globalconf.screen->root,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_ACTIVE_WINDOW, XCB_ATOM_WINDOW, 32, 1, &win);
|
2009-10-08 14:49:41 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-10-08 14:53:46 +02:00
|
|
|
static int
|
|
|
|
ewmh_update_net_client_list(lua_State *L)
|
|
|
|
{
|
|
|
|
xcb_window_t *wins = p_alloca(xcb_window_t, globalconf.clients.len);
|
|
|
|
|
|
|
|
int n = 0;
|
|
|
|
foreach(client, globalconf.clients)
|
|
|
|
wins[n++] = (*client)->window;
|
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
|
|
|
globalconf.screen->root,
|
2010-09-15 21:25:54 +02:00
|
|
|
_NET_CLIENT_LIST, XCB_ATOM_WINDOW, 32, n, wins);
|
2009-10-08 14:53:46 +02:00
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2015-07-05 14:45:51 +02:00
|
|
|
static int
|
|
|
|
ewmh_client_update_frame_extents(lua_State *L)
|
|
|
|
{
|
|
|
|
client_t *c = luaA_checkudata(L, 1, &client_class);;
|
|
|
|
uint32_t extents[4];
|
|
|
|
|
|
|
|
extents[0] = c->border_width + c->titlebar[CLIENT_TITLEBAR_LEFT].size;
|
|
|
|
extents[1] = c->border_width + c->titlebar[CLIENT_TITLEBAR_RIGHT].size;
|
|
|
|
extents[2] = c->border_width + c->titlebar[CLIENT_TITLEBAR_TOP].size;
|
|
|
|
extents[3] = c->border_width + c->titlebar[CLIENT_TITLEBAR_BOTTOM].size;
|
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
|
|
|
c->window, _NET_FRAME_EXTENTS, XCB_ATOM_CARDINAL, 32, 4, extents);
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2007-12-27 17:27:20 +01:00
|
|
|
void
|
2010-08-16 13:47:40 +02:00
|
|
|
ewmh_init(void)
|
2007-12-27 17:27:20 +01:00
|
|
|
{
|
2008-06-17 21:25:23 +02:00
|
|
|
xcb_window_t father;
|
2010-08-16 14:10:58 +02:00
|
|
|
xcb_screen_t *xscreen = globalconf.screen;
|
2008-06-30 18:25:01 +02:00
|
|
|
xcb_atom_t atom[] =
|
|
|
|
{
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_SUPPORTED,
|
|
|
|
_NET_SUPPORTING_WM_CHECK,
|
2009-04-04 13:04:19 +02:00
|
|
|
_NET_STARTUP_ID,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_CLIENT_LIST,
|
|
|
|
_NET_CLIENT_LIST_STACKING,
|
|
|
|
_NET_NUMBER_OF_DESKTOPS,
|
|
|
|
_NET_CURRENT_DESKTOP,
|
|
|
|
_NET_DESKTOP_NAMES,
|
|
|
|
_NET_ACTIVE_WINDOW,
|
|
|
|
_NET_CLOSE_WINDOW,
|
2015-07-05 14:45:51 +02:00
|
|
|
_NET_FRAME_EXTENTS,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_WM_NAME,
|
2008-09-03 22:15:14 +02:00
|
|
|
_NET_WM_STRUT_PARTIAL,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_WM_ICON_NAME,
|
|
|
|
_NET_WM_VISIBLE_ICON_NAME,
|
|
|
|
_NET_WM_DESKTOP,
|
|
|
|
_NET_WM_WINDOW_TYPE,
|
|
|
|
_NET_WM_WINDOW_TYPE_DESKTOP,
|
|
|
|
_NET_WM_WINDOW_TYPE_DOCK,
|
2008-11-30 01:47:24 +01:00
|
|
|
_NET_WM_WINDOW_TYPE_TOOLBAR,
|
|
|
|
_NET_WM_WINDOW_TYPE_MENU,
|
|
|
|
_NET_WM_WINDOW_TYPE_UTILITY,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_WM_WINDOW_TYPE_SPLASH,
|
|
|
|
_NET_WM_WINDOW_TYPE_DIALOG,
|
2009-02-13 11:25:38 +01:00
|
|
|
_NET_WM_WINDOW_TYPE_DROPDOWN_MENU,
|
|
|
|
_NET_WM_WINDOW_TYPE_POPUP_MENU,
|
|
|
|
_NET_WM_WINDOW_TYPE_TOOLTIP,
|
|
|
|
_NET_WM_WINDOW_TYPE_NOTIFICATION,
|
|
|
|
_NET_WM_WINDOW_TYPE_COMBO,
|
|
|
|
_NET_WM_WINDOW_TYPE_DND,
|
2008-11-30 01:47:24 +01:00
|
|
|
_NET_WM_WINDOW_TYPE_NORMAL,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_WM_ICON,
|
|
|
|
_NET_WM_PID,
|
|
|
|
_NET_WM_STATE,
|
|
|
|
_NET_WM_STATE_STICKY,
|
|
|
|
_NET_WM_STATE_SKIP_TASKBAR,
|
|
|
|
_NET_WM_STATE_FULLSCREEN,
|
2008-11-25 11:54:38 +01:00
|
|
|
_NET_WM_STATE_MAXIMIZED_HORZ,
|
|
|
|
_NET_WM_STATE_MAXIMIZED_VERT,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_WM_STATE_ABOVE,
|
|
|
|
_NET_WM_STATE_BELOW,
|
|
|
|
_NET_WM_STATE_MODAL,
|
|
|
|
_NET_WM_STATE_HIDDEN,
|
|
|
|
_NET_WM_STATE_DEMANDS_ATTENTION
|
2008-06-30 18:25:01 +02:00
|
|
|
};
|
|
|
|
int i;
|
2007-12-27 17:27:20 +01:00
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
xscreen->root, _NET_SUPPORTED, XCB_ATOM_ATOM, 32,
|
2008-06-30 18:25:01 +02:00
|
|
|
countof(atom), atom);
|
2008-06-17 21:25:23 +02:00
|
|
|
|
|
|
|
/* create our own window */
|
|
|
|
father = xcb_generate_id(globalconf.connection);
|
|
|
|
xcb_create_window(globalconf.connection, xscreen->root_depth,
|
|
|
|
father, xscreen->root, -1, -1, 1, 1, 0,
|
|
|
|
XCB_COPY_FROM_PARENT, xscreen->root_visual, 0, NULL);
|
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
xscreen->root, _NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32,
|
2008-06-17 22:12:30 +02:00
|
|
|
1, &father);
|
2008-06-17 21:25:23 +02:00
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
father, _NET_SUPPORTING_WM_CHECK, XCB_ATOM_WINDOW, 32,
|
2008-06-17 22:12:30 +02:00
|
|
|
1, &father);
|
2008-06-17 22:47:31 +02:00
|
|
|
|
2008-06-18 08:55:31 +02:00
|
|
|
/* set the window manager name */
|
2008-06-17 22:47:31 +02:00
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2008-06-30 18:55:14 +02:00
|
|
|
father, _NET_WM_NAME, UTF8_STRING, 8, 7, "awesome");
|
2008-06-18 08:55:31 +02:00
|
|
|
|
2015-11-07 11:48:10 +01:00
|
|
|
/* Set an instance, just because we can */
|
|
|
|
xwindow_set_class_instance(father);
|
|
|
|
|
2008-06-18 08:55:31 +02:00
|
|
|
/* set the window manager PID */
|
|
|
|
i = getpid();
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
father, _NET_WM_PID, XCB_ATOM_CARDINAL, 32, 1, &i);
|
2017-01-25 14:55:27 +01:00
|
|
|
}
|
2009-02-13 10:57:42 +01:00
|
|
|
|
2017-01-25 14:55:27 +01:00
|
|
|
void
|
|
|
|
ewmh_init_lua(void)
|
|
|
|
{
|
|
|
|
lua_State *L = globalconf_get_lua_State();
|
2009-10-08 14:08:22 +02:00
|
|
|
|
2014-12-06 11:56:58 +01:00
|
|
|
luaA_class_connect_signal(L, &client_class, "focus", ewmh_update_net_active_window);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "unfocus", ewmh_update_net_active_window);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "manage", ewmh_update_net_client_list);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "unmanage", ewmh_update_net_client_list);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::modal" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::fullscreen" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::maximized_horizontal" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::maximized_vertical" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::sticky" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::skip_taskbar" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::above" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::below" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::minimized" , ewmh_client_update_hints);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::urgent" , ewmh_client_update_hints);
|
2015-07-05 14:45:51 +02:00
|
|
|
luaA_class_connect_signal(L, &client_class, "property::titlebar_top" , ewmh_client_update_frame_extents);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::titlebar_bottom" , ewmh_client_update_frame_extents);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::titlebar_right" , ewmh_client_update_frame_extents);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::titlebar_left" , ewmh_client_update_frame_extents);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "property::border_width" , ewmh_client_update_frame_extents);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "manage", ewmh_client_update_frame_extents);
|
2016-05-15 15:31:57 +02:00
|
|
|
/* NET_CURRENT_DESKTOP handling */
|
|
|
|
luaA_class_connect_signal(L, &client_class, "focus", ewmh_update_net_current_desktop);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "unfocus", ewmh_update_net_current_desktop);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "tagged", ewmh_update_net_current_desktop);
|
|
|
|
luaA_class_connect_signal(L, &client_class, "untagged", ewmh_update_net_current_desktop);
|
|
|
|
luaA_class_connect_signal(L, &tag_class, "property::selected", ewmh_update_net_current_desktop);
|
2007-12-27 18:01:36 +01:00
|
|
|
}
|
2007-12-27 17:27:20 +01:00
|
|
|
|
2008-06-17 21:47:57 +02:00
|
|
|
/** Set the client list in stacking order, bottom to top.
|
|
|
|
*/
|
|
|
|
void
|
2010-08-16 13:47:40 +02:00
|
|
|
ewmh_update_net_client_list_stacking(void)
|
2008-06-17 21:47:57 +02:00
|
|
|
{
|
|
|
|
int n = 0;
|
2009-04-17 23:26:26 +02:00
|
|
|
xcb_window_t *wins = p_alloca(xcb_window_t, globalconf.stack.len);
|
2008-06-17 21:47:57 +02:00
|
|
|
|
2009-04-17 23:26:26 +02:00
|
|
|
foreach(client, globalconf.stack)
|
2010-08-16 13:47:40 +02:00
|
|
|
wins[n++] = (*client)->window;
|
2008-06-17 21:47:57 +02:00
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-16 14:10:58 +02:00
|
|
|
globalconf.screen->root,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_CLIENT_LIST_STACKING, XCB_ATOM_WINDOW, 32, n, wins);
|
2008-06-17 21:47:57 +02:00
|
|
|
}
|
|
|
|
|
2007-12-27 18:18:12 +01:00
|
|
|
void
|
2010-08-16 13:47:40 +02:00
|
|
|
ewmh_update_net_numbers_of_desktop(void)
|
2007-12-27 18:18:12 +01:00
|
|
|
{
|
2012-10-20 17:33:32 +02:00
|
|
|
uint32_t count = globalconf.tags.len;
|
2007-12-27 18:18:12 +01:00
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-16 14:10:58 +02:00
|
|
|
globalconf.screen->root,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_NUMBER_OF_DESKTOPS, XCB_ATOM_CARDINAL, 32, 1, &count);
|
2007-12-27 18:18:12 +01:00
|
|
|
}
|
|
|
|
|
2016-05-15 15:31:57 +02:00
|
|
|
int
|
|
|
|
ewmh_update_net_current_desktop(lua_State *L)
|
2007-12-27 18:42:20 +01:00
|
|
|
{
|
2016-05-15 15:31:57 +02:00
|
|
|
uint32_t idx = tags_get_current_or_first_selected_index();
|
2007-12-27 18:42:20 +01:00
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-16 14:10:58 +02:00
|
|
|
globalconf.screen->root,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_CURRENT_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &idx);
|
2016-05-15 15:31:57 +02:00
|
|
|
return 0;
|
2007-12-27 18:42:20 +01:00
|
|
|
}
|
|
|
|
|
2007-12-27 19:11:18 +01:00
|
|
|
void
|
2010-08-16 13:47:40 +02:00
|
|
|
ewmh_update_net_desktop_names(void)
|
2007-12-27 19:11:18 +01:00
|
|
|
{
|
2008-06-23 17:37:19 +02:00
|
|
|
buffer_t buf;
|
2007-12-27 19:11:18 +01:00
|
|
|
|
2008-06-23 17:37:19 +02:00
|
|
|
buffer_inita(&buf, BUFSIZ);
|
|
|
|
|
2012-10-20 17:33:32 +02:00
|
|
|
foreach(tag, globalconf.tags)
|
2007-12-27 19:11:18 +01:00
|
|
|
{
|
2009-07-29 17:38:48 +02:00
|
|
|
buffer_adds(&buf, tag_get_name(*tag));
|
2008-06-23 17:37:19 +02:00
|
|
|
buffer_addc(&buf, '\0');
|
2007-12-27 19:11:18 +01:00
|
|
|
}
|
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-16 14:10:58 +02:00
|
|
|
globalconf.screen->root,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_DESKTOP_NAMES, UTF8_STRING, 8, buf.len, buf.s);
|
2008-06-23 17:37:19 +02:00
|
|
|
buffer_wipe(&buf);
|
2007-12-27 19:33:01 +01:00
|
|
|
}
|
|
|
|
|
2007-12-27 22:39:29 +01:00
|
|
|
static void
|
2008-04-11 11:35:11 +02:00
|
|
|
ewmh_process_state_atom(client_t *c, xcb_atom_t state, int set)
|
2007-12-27 22:39:29 +01:00
|
|
|
{
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_State *L = globalconf_get_lua_State();
|
|
|
|
luaA_object_push(L, c);
|
2009-08-17 17:02:45 +02:00
|
|
|
|
2008-06-30 18:55:14 +02:00
|
|
|
if(state == _NET_WM_STATE_STICKY)
|
2007-12-27 22:39:29 +01:00
|
|
|
{
|
2008-08-21 16:29:53 +02:00
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_sticky(L, -1, false);
|
2008-08-21 16:29:53 +02:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_sticky(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_sticky(L, -1, !c->sticky);
|
2007-12-27 22:39:29 +01:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_SKIP_TASKBAR)
|
2008-01-03 13:15:15 +01:00
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_skip_taskbar(L, -1, false);
|
2008-01-03 13:15:15 +01:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_skip_taskbar(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_skip_taskbar(L, -1, !c->skip_taskbar);
|
2008-01-03 13:15:15 +01:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_FULLSCREEN)
|
2007-12-28 18:31:31 +01:00
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_fullscreen(L, -1, false);
|
2008-01-06 14:40:23 +01:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_fullscreen(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_fullscreen(L, -1, !c->fullscreen);
|
2007-12-28 18:31:31 +01:00
|
|
|
}
|
2008-11-25 11:54:38 +01:00
|
|
|
else if(state == _NET_WM_STATE_MAXIMIZED_HORZ)
|
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_maximized_horizontal(L, -1, false);
|
2008-11-25 11:54:38 +01:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_maximized_horizontal(L, -1, true);
|
2008-11-25 11:54:38 +01:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_maximized_horizontal(L, -1, !c->maximized_horizontal);
|
2008-11-25 11:54:38 +01:00
|
|
|
}
|
|
|
|
else if(state == _NET_WM_STATE_MAXIMIZED_VERT)
|
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_maximized_vertical(L, -1, false);
|
2008-11-25 11:54:38 +01:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_maximized_vertical(L, -1, true);
|
2008-11-25 11:54:38 +01:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_maximized_vertical(L, -1, !c->maximized_vertical);
|
2008-11-25 11:54:38 +01:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_ABOVE)
|
2008-04-08 19:52:59 +02:00
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_above(L, -1, false);
|
2008-04-08 19:52:59 +02:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_above(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_above(L, -1, !c->above);
|
2008-04-08 19:52:59 +02:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_BELOW)
|
2008-04-08 19:52:59 +02:00
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_below(L, -1, false);
|
2008-04-08 19:52:59 +02:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_below(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_below(L, -1, !c->below);
|
2008-04-08 19:52:59 +02:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_MODAL)
|
2008-06-13 14:41:10 +02:00
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_modal(L, -1, false);
|
2008-06-13 14:41:10 +02:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_modal(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_modal(L, -1, !c->modal);
|
2008-06-13 14:41:10 +02:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_HIDDEN)
|
2008-06-13 17:33:59 +02:00
|
|
|
{
|
|
|
|
if(set == _NET_WM_STATE_REMOVE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_minimized(L, -1, false);
|
2008-06-13 17:33:59 +02:00
|
|
|
else if(set == _NET_WM_STATE_ADD)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_minimized(L, -1, true);
|
2008-09-18 09:44:51 +02:00
|
|
|
else if(set == _NET_WM_STATE_TOGGLE)
|
2014-12-06 11:56:58 +01:00
|
|
|
client_set_minimized(L, -1, !c->minimized);
|
2008-06-13 17:33:59 +02:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(state == _NET_WM_STATE_DEMANDS_ATTENTION)
|
2008-06-17 22:57:54 +02:00
|
|
|
{
|
2014-04-16 06:32:44 +02:00
|
|
|
if(set == _NET_WM_STATE_REMOVE) {
|
|
|
|
lua_pushboolean(L, false);
|
|
|
|
luaA_object_emit_signal(L, -2, "request::urgent", 1);
|
|
|
|
}
|
|
|
|
else if(set == _NET_WM_STATE_ADD) {
|
|
|
|
lua_pushboolean(L, true);
|
|
|
|
luaA_object_emit_signal(L, -2, "request::urgent", 1);
|
|
|
|
}
|
|
|
|
else if(set == _NET_WM_STATE_TOGGLE) {
|
|
|
|
lua_pushboolean(L, !c->urgent);
|
|
|
|
luaA_object_emit_signal(L, -2, "request::urgent", 1);
|
|
|
|
}
|
2008-06-17 22:57:54 +02:00
|
|
|
}
|
2010-08-03 11:25:54 +02:00
|
|
|
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_pop(L, 1);
|
2007-12-27 22:39:29 +01:00
|
|
|
}
|
|
|
|
|
2014-03-17 15:33:28 +01:00
|
|
|
static void
|
|
|
|
ewmh_process_desktop(client_t *c, uint32_t desktop)
|
|
|
|
{
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_State *L = globalconf_get_lua_State();
|
2014-03-17 15:33:28 +01:00
|
|
|
int idx = desktop;
|
|
|
|
if(desktop == 0xffffffff)
|
2014-03-17 15:38:20 +01:00
|
|
|
{
|
2014-12-06 11:56:58 +01:00
|
|
|
luaA_object_push(L, c);
|
2016-04-17 09:52:59 +02:00
|
|
|
lua_pushboolean(L, true);
|
2014-12-06 11:56:58 +01:00
|
|
|
luaA_object_emit_signal(L, -2, "request::tag", 1);
|
2014-03-17 16:15:20 +01:00
|
|
|
/* Pop the client, arguments are already popped */
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_pop(L, 1);
|
2014-03-17 15:38:20 +01:00
|
|
|
}
|
2014-03-17 15:33:28 +01:00
|
|
|
else if (idx >= 0 && idx < globalconf.tags.len)
|
2014-03-17 16:15:20 +01:00
|
|
|
{
|
2014-12-06 11:56:58 +01:00
|
|
|
luaA_object_push(L, c);
|
|
|
|
luaA_object_push(L, globalconf.tags.tab[idx]);
|
|
|
|
luaA_object_emit_signal(L, -2, "request::tag", 1);
|
2014-03-17 16:15:20 +01:00
|
|
|
/* Pop the client, arguments are already popped */
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_pop(L, 1);
|
2014-03-17 16:15:20 +01:00
|
|
|
}
|
2014-03-17 15:33:28 +01:00
|
|
|
}
|
|
|
|
|
2008-06-14 18:12:16 +02:00
|
|
|
int
|
2008-03-21 16:50:17 +01:00
|
|
|
ewmh_process_client_message(xcb_client_message_event_t *ev)
|
2007-12-27 20:49:38 +01:00
|
|
|
{
|
2008-04-11 11:35:11 +02:00
|
|
|
client_t *c;
|
2007-12-28 22:16:27 +01:00
|
|
|
|
2008-06-30 18:55:14 +02:00
|
|
|
if(ev->type == _NET_CURRENT_DESKTOP)
|
2014-03-08 15:33:34 +01:00
|
|
|
{
|
|
|
|
int idx = ev->data.data32[0];
|
|
|
|
if (idx >= 0 && idx < globalconf.tags.len)
|
|
|
|
{
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_State *L = globalconf_get_lua_State();
|
|
|
|
luaA_object_push(L, globalconf.tags.tab[idx]);
|
|
|
|
luaA_object_emit_signal(L, -1, "request::select", 0);
|
|
|
|
lua_pop(L, 1);
|
2014-03-08 15:33:34 +01:00
|
|
|
}
|
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(ev->type == _NET_CLOSE_WINDOW)
|
2007-12-27 22:39:29 +01:00
|
|
|
{
|
2008-06-05 09:25:38 +02:00
|
|
|
if((c = client_getbywin(ev->window)))
|
2007-12-27 20:49:38 +01:00
|
|
|
client_kill(c);
|
2007-12-27 22:39:29 +01:00
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(ev->type == _NET_WM_DESKTOP)
|
2008-06-18 00:08:04 +02:00
|
|
|
{
|
|
|
|
if((c = client_getbywin(ev->window)))
|
|
|
|
{
|
2014-03-17 15:33:28 +01:00
|
|
|
ewmh_process_desktop(c, ev->data.data32[0]);
|
2008-06-18 00:08:04 +02:00
|
|
|
}
|
|
|
|
}
|
2008-06-30 18:55:14 +02:00
|
|
|
else if(ev->type == _NET_WM_STATE)
|
2007-12-27 22:39:29 +01:00
|
|
|
{
|
2008-06-05 09:25:38 +02:00
|
|
|
if((c = client_getbywin(ev->window)))
|
2007-12-27 22:39:29 +01:00
|
|
|
{
|
2008-03-21 16:50:17 +01:00
|
|
|
ewmh_process_state_atom(c, (xcb_atom_t) ev->data.data32[1], ev->data.data32[0]);
|
|
|
|
if(ev->data.data32[2])
|
|
|
|
ewmh_process_state_atom(c, (xcb_atom_t) ev->data.data32[2],
|
|
|
|
ev->data.data32[0]);
|
2007-12-27 22:39:29 +01:00
|
|
|
}
|
|
|
|
}
|
2008-12-15 10:04:46 +01:00
|
|
|
else if(ev->type == _NET_ACTIVE_WINDOW)
|
|
|
|
{
|
2013-01-20 15:35:10 +01:00
|
|
|
if((c = client_getbywin(ev->window))) {
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_State *L = globalconf_get_lua_State();
|
|
|
|
luaA_object_push(L, c);
|
|
|
|
lua_pushstring(L, "ewmh");
|
2015-06-19 22:24:12 +02:00
|
|
|
|
|
|
|
/* Create table argument with raise=true. */
|
|
|
|
lua_newtable(L);
|
|
|
|
lua_pushstring(L, "raise");
|
2015-05-13 22:11:07 +02:00
|
|
|
lua_pushboolean(L, true);
|
2015-06-19 22:24:12 +02:00
|
|
|
lua_settable(L, -3);
|
|
|
|
|
2015-05-13 22:11:07 +02:00
|
|
|
luaA_object_emit_signal(L, -3, "request::activate", 2);
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_pop(L, 1);
|
2013-01-20 15:35:10 +01:00
|
|
|
}
|
2008-12-15 10:04:46 +01:00
|
|
|
}
|
2008-06-14 18:12:16 +02:00
|
|
|
|
|
|
|
return 0;
|
2007-12-27 22:39:29 +01:00
|
|
|
}
|
|
|
|
|
2009-01-02 11:55:46 +01:00
|
|
|
/** Update the client active desktop.
|
|
|
|
* This is "wrong" since it can be on several tags, but EWMH has a strict view
|
|
|
|
* of desktop system so just take the first tag.
|
|
|
|
* \param c The client.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ewmh_client_update_desktop(client_t *c)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2012-10-20 17:33:32 +02:00
|
|
|
for(i = 0; i < globalconf.tags.len; i++)
|
|
|
|
if(is_client_tagged(c, globalconf.tags.tab[i]))
|
2009-01-02 11:55:46 +01:00
|
|
|
{
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
c->window, _NET_WM_DESKTOP, XCB_ATOM_CARDINAL, 32, 1, &i);
|
2009-01-02 11:55:46 +01:00
|
|
|
return;
|
|
|
|
}
|
2010-06-13 08:57:31 +02:00
|
|
|
/* It doesn't have any tags, remove the property */
|
|
|
|
xcb_delete_property(globalconf.connection, c->window, _NET_WM_DESKTOP);
|
2009-01-02 11:55:46 +01:00
|
|
|
}
|
|
|
|
|
2009-02-07 19:40:07 +01:00
|
|
|
/** Update the client struts.
|
2009-08-25 04:55:10 +02:00
|
|
|
* \param window The window to update the struts for.
|
|
|
|
* \param strut The strut type to update the window with.
|
2009-02-07 19:40:07 +01:00
|
|
|
*/
|
|
|
|
void
|
2009-08-18 12:01:44 +02:00
|
|
|
ewmh_update_strut(xcb_window_t window, strut_t *strut)
|
2009-02-07 19:40:07 +01:00
|
|
|
{
|
2009-10-01 16:36:46 +02:00
|
|
|
if(window)
|
2009-02-07 19:40:07 +01:00
|
|
|
{
|
2009-10-01 16:36:46 +02:00
|
|
|
const uint32_t state[] =
|
|
|
|
{
|
|
|
|
strut->left,
|
|
|
|
strut->right,
|
|
|
|
strut->top,
|
|
|
|
strut->bottom,
|
|
|
|
strut->left_start_y,
|
|
|
|
strut->left_end_y,
|
|
|
|
strut->right_start_y,
|
|
|
|
strut->right_end_y,
|
|
|
|
strut->top_start_x,
|
|
|
|
strut->top_end_x,
|
|
|
|
strut->bottom_start_x,
|
|
|
|
strut->bottom_end_x
|
|
|
|
};
|
|
|
|
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
2010-08-08 18:31:07 +02:00
|
|
|
window, _NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 32, countof(state), state);
|
2009-10-01 16:36:46 +02:00
|
|
|
}
|
2009-02-07 19:40:07 +01:00
|
|
|
}
|
|
|
|
|
2010-09-28 13:07:31 +02:00
|
|
|
/** Update the window type.
|
|
|
|
* \param window The window to update.
|
|
|
|
* \param type The new type to set.
|
|
|
|
*/
|
|
|
|
void
|
|
|
|
ewmh_update_window_type(xcb_window_t window, uint32_t type)
|
|
|
|
{
|
|
|
|
xcb_change_property(globalconf.connection, XCB_PROP_MODE_REPLACE,
|
|
|
|
window, _NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 32, 1, &type);
|
|
|
|
}
|
|
|
|
|
2008-09-18 13:51:10 +02:00
|
|
|
void
|
|
|
|
ewmh_client_check_hints(client_t *c)
|
2007-12-27 22:39:29 +01:00
|
|
|
{
|
2008-03-21 16:50:17 +01:00
|
|
|
xcb_atom_t *state;
|
|
|
|
void *data = NULL;
|
2008-06-18 00:08:04 +02:00
|
|
|
xcb_get_property_cookie_t c0, c1, c2;
|
2008-03-21 16:50:17 +01:00
|
|
|
xcb_get_property_reply_t *reply;
|
|
|
|
|
|
|
|
/* Send the GetProperty requests which will be processed later */
|
2009-08-17 17:02:45 +02:00
|
|
|
c0 = xcb_get_property_unchecked(globalconf.connection, false, c->window,
|
2008-06-30 18:55:14 +02:00
|
|
|
_NET_WM_DESKTOP, XCB_GET_PROPERTY_TYPE_ANY, 0, 1);
|
2008-06-18 00:08:04 +02:00
|
|
|
|
2009-08-17 17:02:45 +02:00
|
|
|
c1 = xcb_get_property_unchecked(globalconf.connection, false, c->window,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_WM_STATE, XCB_ATOM_ATOM, 0, UINT32_MAX);
|
2008-03-21 16:50:17 +01:00
|
|
|
|
2009-08-17 17:02:45 +02:00
|
|
|
c2 = xcb_get_property_unchecked(globalconf.connection, false, c->window,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_WM_WINDOW_TYPE, XCB_ATOM_ATOM, 0, UINT32_MAX);
|
2008-03-21 16:50:17 +01:00
|
|
|
|
2008-06-18 00:08:04 +02:00
|
|
|
reply = xcb_get_property_reply(globalconf.connection, c0, NULL);
|
|
|
|
if(reply && reply->value_len && (data = xcb_get_property_value(reply)))
|
|
|
|
{
|
2014-03-17 15:33:28 +01:00
|
|
|
ewmh_process_desktop(c, *(uint32_t *) data);
|
2008-06-18 00:08:04 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
p_delete(&reply);
|
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
reply = xcb_get_property_reply(globalconf.connection, c1, NULL);
|
|
|
|
if(reply && (data = xcb_get_property_value(reply)))
|
2007-12-28 20:48:29 +01:00
|
|
|
{
|
2008-03-21 16:50:17 +01:00
|
|
|
state = (xcb_atom_t *) data;
|
2009-08-19 16:40:16 +02:00
|
|
|
for(int i = 0; i < xcb_get_property_value_length(reply) / ssizeof(xcb_atom_t); i++)
|
2007-12-28 20:48:29 +01:00
|
|
|
ewmh_process_state_atom(c, state[i], _NET_WM_STATE_ADD);
|
|
|
|
}
|
2007-12-27 22:39:29 +01:00
|
|
|
|
2008-03-21 16:50:17 +01:00
|
|
|
p_delete(&reply);
|
|
|
|
|
|
|
|
reply = xcb_get_property_reply(globalconf.connection, c2, NULL);
|
|
|
|
if(reply && (data = xcb_get_property_value(reply)))
|
2007-12-28 20:48:29 +01:00
|
|
|
{
|
2016-05-14 14:10:27 +02:00
|
|
|
c->has_NET_WM_WINDOW_TYPE = true;
|
2008-03-21 16:50:17 +01:00
|
|
|
state = (xcb_atom_t *) data;
|
2009-08-19 16:40:16 +02:00
|
|
|
for(int i = 0; i < xcb_get_property_value_length(reply) / ssizeof(xcb_atom_t); i++)
|
2008-09-03 14:59:18 +02:00
|
|
|
if(state[i] == _NET_WM_WINDOW_TYPE_DESKTOP)
|
2008-10-02 14:07:42 +02:00
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_DESKTOP);
|
2008-09-03 14:59:18 +02:00
|
|
|
else if(state[i] == _NET_WM_WINDOW_TYPE_DIALOG)
|
2008-10-02 14:07:42 +02:00
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_DIALOG);
|
2008-09-03 14:59:18 +02:00
|
|
|
else if(state[i] == _NET_WM_WINDOW_TYPE_SPLASH)
|
2008-10-02 14:07:42 +02:00
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_SPLASH);
|
2008-09-03 14:59:18 +02:00
|
|
|
else if(state[i] == _NET_WM_WINDOW_TYPE_DOCK)
|
2008-10-02 14:07:42 +02:00
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_DOCK);
|
2008-11-30 01:47:24 +01:00
|
|
|
else if(state[i] == _NET_WM_WINDOW_TYPE_MENU)
|
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_MENU);
|
|
|
|
else if(state[i] == _NET_WM_WINDOW_TYPE_TOOLBAR)
|
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_TOOLBAR);
|
|
|
|
else if(state[i] == _NET_WM_WINDOW_TYPE_UTILITY)
|
|
|
|
c->type = MAX(c->type, WINDOW_TYPE_UTILITY);
|
2016-05-14 14:10:27 +02:00
|
|
|
} else
|
|
|
|
c->has_NET_WM_WINDOW_TYPE = false;
|
2008-03-21 16:50:17 +01:00
|
|
|
|
|
|
|
p_delete(&reply);
|
2007-12-27 20:49:38 +01:00
|
|
|
}
|
|
|
|
|
2009-02-07 19:40:07 +01:00
|
|
|
/** Process the WM strut of a client.
|
2008-09-03 22:15:14 +02:00
|
|
|
* \param c The client.
|
|
|
|
*/
|
|
|
|
void
|
2010-08-09 13:04:08 +02:00
|
|
|
ewmh_process_client_strut(client_t *c)
|
2008-09-03 22:15:14 +02:00
|
|
|
{
|
|
|
|
void *data;
|
2010-08-09 13:04:08 +02:00
|
|
|
xcb_get_property_reply_t *strut_r;
|
2008-09-03 22:15:14 +02:00
|
|
|
|
2010-08-09 13:04:08 +02:00
|
|
|
xcb_get_property_cookie_t strut_q = xcb_get_property_unchecked(globalconf.connection, false, c->window,
|
|
|
|
_NET_WM_STRUT_PARTIAL, XCB_ATOM_CARDINAL, 0, 12);
|
|
|
|
strut_r = xcb_get_property_reply(globalconf.connection, strut_q, NULL);
|
2008-09-03 22:15:14 +02:00
|
|
|
|
|
|
|
if(strut_r
|
|
|
|
&& strut_r->value_len
|
|
|
|
&& (data = xcb_get_property_value(strut_r)))
|
|
|
|
{
|
|
|
|
uint32_t *strut = data;
|
|
|
|
|
|
|
|
if(c->strut.left != strut[0]
|
|
|
|
|| c->strut.right != strut[1]
|
|
|
|
|| c->strut.top != strut[2]
|
|
|
|
|| c->strut.bottom != strut[3]
|
|
|
|
|| c->strut.left_start_y != strut[4]
|
|
|
|
|| c->strut.left_end_y != strut[5]
|
|
|
|
|| c->strut.right_start_y != strut[6]
|
|
|
|
|| c->strut.right_end_y != strut[7]
|
|
|
|
|| c->strut.top_start_x != strut[8]
|
|
|
|
|| c->strut.top_end_x != strut[9]
|
|
|
|
|| c->strut.bottom_start_x != strut[10]
|
|
|
|
|| c->strut.bottom_end_x != strut[11])
|
|
|
|
{
|
|
|
|
c->strut.left = strut[0];
|
|
|
|
c->strut.right = strut[1];
|
|
|
|
c->strut.top = strut[2];
|
|
|
|
c->strut.bottom = strut[3];
|
|
|
|
c->strut.left_start_y = strut[4];
|
|
|
|
c->strut.left_end_y = strut[5];
|
|
|
|
c->strut.right_start_y = strut[6];
|
|
|
|
c->strut.right_end_y = strut[7];
|
|
|
|
c->strut.top_start_x = strut[8];
|
|
|
|
c->strut.top_end_x = strut[9];
|
|
|
|
c->strut.bottom_start_x = strut[10];
|
|
|
|
c->strut.bottom_end_x = strut[11];
|
|
|
|
|
2014-12-06 11:56:58 +01:00
|
|
|
lua_State *L = globalconf_get_lua_State();
|
|
|
|
luaA_object_push(L, c);
|
|
|
|
luaA_object_emit_signal(L, -1, "property::struts", 0);
|
|
|
|
lua_pop(L, 1);
|
2008-09-03 22:15:14 +02:00
|
|
|
}
|
|
|
|
}
|
2008-09-16 14:09:56 +02:00
|
|
|
|
2010-08-09 13:04:08 +02:00
|
|
|
p_delete(&strut_r);
|
2008-09-03 22:15:14 +02:00
|
|
|
}
|
|
|
|
|
2008-08-13 02:02:19 +02:00
|
|
|
/** Send request to get NET_WM_ICON (EWMH)
|
2008-07-29 16:44:57 +02:00
|
|
|
* \param w The window.
|
2008-08-13 02:02:19 +02:00
|
|
|
* \return The cookie associated with the request.
|
|
|
|
*/
|
|
|
|
xcb_get_property_cookie_t
|
|
|
|
ewmh_window_icon_get_unchecked(xcb_window_t w)
|
|
|
|
{
|
|
|
|
return xcb_get_property_unchecked(globalconf.connection, false, w,
|
2010-08-08 18:31:07 +02:00
|
|
|
_NET_WM_ICON, XCB_ATOM_CARDINAL, 0, UINT32_MAX);
|
2008-08-13 02:02:19 +02:00
|
|
|
}
|
|
|
|
|
2012-05-28 09:29:47 +02:00
|
|
|
static cairo_surface_t *
|
2015-11-30 20:26:26 +01:00
|
|
|
ewmh_window_icon_from_reply(xcb_get_property_reply_t *r, uint32_t preferred_size)
|
2008-01-03 19:02:23 +01:00
|
|
|
{
|
2015-11-30 20:26:26 +01:00
|
|
|
uint32_t *data, *end, *found_data = 0;
|
|
|
|
uint32_t found_size = 0;
|
2008-03-21 16:50:17 +01:00
|
|
|
|
2010-08-08 18:31:07 +02:00
|
|
|
if(!r || r->type != XCB_ATOM_CARDINAL || r->format != 32 || r->length < 2)
|
2009-05-12 11:05:34 +02:00
|
|
|
return 0;
|
2008-01-03 19:02:23 +01:00
|
|
|
|
2009-05-12 11:05:34 +02:00
|
|
|
data = (uint32_t *) xcb_get_property_value(r);
|
2015-11-30 20:26:26 +01:00
|
|
|
if (!data) return 0;
|
|
|
|
|
|
|
|
end = data + r->length;
|
2009-05-12 11:08:43 +02:00
|
|
|
|
2015-11-30 20:26:26 +01:00
|
|
|
/* Goes over the icon data and picks the icon that best matches the size preference.
|
|
|
|
* In case the size match is not exact, picks the closest bigger size if present,
|
|
|
|
* closest smaller size otherwise.
|
2009-05-12 11:08:43 +02:00
|
|
|
*/
|
2015-11-30 20:26:26 +01:00
|
|
|
while (data + 1 < end) {
|
|
|
|
/* check whether the data size specified by width and height fits into the array we got */
|
|
|
|
uint64_t data_size = (uint64_t) data[0] * data[1];
|
|
|
|
if (data_size > (uint64_t) (end - data - 2)) break;
|
|
|
|
|
|
|
|
/* use the greater of the two dimensions to match against the preferred size */
|
|
|
|
uint32_t size = MAX(data[0], data[1]);
|
2015-12-23 14:16:24 +01:00
|
|
|
|
2015-11-30 20:26:26 +01:00
|
|
|
/* pick the icon if it's a better match than the one we already have */
|
2015-12-23 14:16:24 +01:00
|
|
|
bool found_icon_too_small = found_size < preferred_size;
|
|
|
|
bool found_icon_too_large = found_size > preferred_size;
|
|
|
|
bool icon_empty = data[0] == 0 || data[1] == 0;
|
|
|
|
bool better_because_bigger = found_icon_too_small && size > found_size;
|
|
|
|
bool better_because_smaller = found_icon_too_large &&
|
|
|
|
size >= preferred_size && size < found_size;
|
2015-12-23 14:19:18 +01:00
|
|
|
if (!icon_empty && (better_because_bigger || better_because_smaller || found_size == 0))
|
2015-11-30 20:26:26 +01:00
|
|
|
{
|
|
|
|
found_data = data;
|
|
|
|
found_size = size;
|
|
|
|
}
|
|
|
|
|
|
|
|
data += data_size + 2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!found_data) return 0;
|
2009-05-12 11:05:34 +02:00
|
|
|
|
2015-11-30 20:26:26 +01:00
|
|
|
return draw_surface_from_data(found_data[0], found_data[1], found_data + 2);
|
2008-09-16 14:09:56 +02:00
|
|
|
}
|
2008-01-03 19:02:23 +01:00
|
|
|
|
2008-09-16 14:09:56 +02:00
|
|
|
/** Get NET_WM_ICON.
|
|
|
|
* \param cookie The cookie.
|
2009-04-09 11:38:56 +02:00
|
|
|
* \return The number of elements on stack.
|
2008-09-16 14:09:56 +02:00
|
|
|
*/
|
2012-05-28 09:29:47 +02:00
|
|
|
cairo_surface_t *
|
2015-11-30 20:26:26 +01:00
|
|
|
ewmh_window_icon_get_reply(xcb_get_property_cookie_t cookie, uint32_t preferred_size)
|
2008-09-16 14:09:56 +02:00
|
|
|
{
|
|
|
|
xcb_get_property_reply_t *r = xcb_get_property_reply(globalconf.connection, cookie, NULL);
|
2015-11-30 20:26:26 +01:00
|
|
|
cairo_surface_t *surface = ewmh_window_icon_from_reply(r, preferred_size);
|
2008-09-16 14:09:56 +02:00
|
|
|
p_delete(&r);
|
2012-05-28 09:29:47 +02:00
|
|
|
return surface;
|
2008-01-03 19:02:23 +01:00
|
|
|
}
|
|
|
|
|
2011-09-11 16:50:01 +02:00
|
|
|
// vim: filetype=c:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:textwidth=80
|