/*
* 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"
#include "timings.h"
#define WINLIST 32
#define CLIENTSTATE 10
#define CLIENTWINDOWTYPE 10
// Fields to match in window mode
typedef struct
{
char *field_name;
gboolean enabled;
} WinModeField;
typedef enum
{
WIN_MATCH_FIELD_TITLE,
WIN_MATCH_FIELD_CLASS,
WIN_MATCH_FIELD_ROLE,
WIN_MATCH_FIELD_NAME,
WIN_MATCH_FIELD_DESKTOP,
WIN_MATCH_NUM_FIELDS,
} WinModeMatchingFields;
static WinModeField matching_window_fields[WIN_MATCH_NUM_FIELDS] = {
{ .field_name = "title", .enabled = TRUE, },
{ .field_name = "class", .enabled = TRUE, },
{ .field_name = "role", .enabled = TRUE, },
{ .field_name = "name", .enabled = TRUE, },
{ .field_name = "desktop", .enabled = TRUE, }
};
static gboolean window_matching_fields_parsed = FALSE;
// 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 ) );