/*
* rofi
*
* MIT/X11 License
* Copyright © 2013-2017 Qball Cow <qball@gmpclient.org>
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
*/
#define G_LOG_DOMAIN "Dialogs.Window"
#include <config.h>
#ifdef WINDOW_MODE
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <unistd.h>
#include <strings.h>
#include <string.h>
#include <errno.h>
#include <xcb/xcb.h>
#include <xcb/xcb_ewmh.h>
#include <xcb/xcb_icccm.h>
#include <xcb/xcb_atom.h>
#include <glib.h>
#include "xcb-internal.h"
#include "xcb.h"
#include "rofi.h"
#include "settings.h"
#include "helper.h"
#include "widgets/textbox.h"
#include "dialogs/window.h"
#define WINLIST 32
#define CLIENTSTATE 10
#define CLIENTWINDOWTYPE 10
// a manageable window
typedef struct
{
xcb_window_t window;
xcb_get_window_attributes_reply_t xattr;
char *title;
char *class;
char *name;
char *role;
int states;
xcb_atom_t state[CLIENTSTATE];
int window_types;
xcb_atom_t window_type[CLIENTWINDOWTYPE];
int active;
int demands;
long hint_flags;
uint32_t wmdesktop;
char *wmdesktopstr;
cairo_surface_t *icon;
gboolean icon_checked;
} client;
// window lists
typedef struct
{
xcb_window_t *array;
client **data;
int len;
} winlist;
typedef struct
{
unsigned int id;
winlist *ids;
// Current window.
unsigned int index;
char *cache;
unsigned int wmdn_len;
unsigned int clf_len;
unsigned int name_len;
unsigned int title_len;
unsigned int role_len;
GRegex *window_regex;
} ModeModePrivateData;
winlist *cache_client = NULL;
/**
* Create a window list, pre-seeded with WINLIST entries.
*
* @returns A new window list.
*/
static winlist* winlist_new ()
{
winlist *l = g_malloc ( sizeof ( winlist ) );
l->len = 0;
l->array = g_malloc_n ( WINLIST + 1, sizeof ( xcb_window_t ) );
l->data = g_malloc_n ( WINLIST + 1, sizeof ( client* ) );
return l;
}
/**
* @param l The winlist.
* @param w The window to add.
* @param d Data pointer.
*
* Add one entry. If Full, extend with WINLIST entries.
*
* @returns 0 if failed, 1 is successful.
*/
static int winlist_append ( winlist *l, xcb_window_t w, client *d )
{
if ( l->len > 0 && !( l->len % WINLIST ) ) {
l->array = g_realloc ( l->array, sizeof ( xcb_window_t ) * ( l->len + WINLIST + 1 ) );
l->data = g_realloc ( l->data, sizeof ( client* ) * ( l->len + WINLIST + 1 ) );
}
// Make clang-check happy.
// TODO: make clang-check clear this should never be 0.
if ( l->data == NULL || l->array == NULL ) {
return 0;
}
l->data[l->len] = d;
l->array[l->len++] = w;
return l->len - 1;
}
static void winlist_empty ( winlist *l )
{
while ( l->len > 0 ) {
client *c = l->data[--l->len];
if ( c != NULL ) {
if ( c->icon ) {
cairo_surface_destroy ( c->icon );
}
g_free ( c->title );
g_free ( c->class );
g_free ( c->name );
g_free ( c->role );
g_free ( c->wmdesktopstr );
g_free ( c );
}
}
}
/**
* @param l The winlist entry
*
* Free the winlist.
*/
static void winlist_free ( winlist *l )
{
if ( l != NULL ) {
winlist_empty ( l );