/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2016 Alberts Muktupāvels
*
* 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, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include "meta-button-layout-private.h"
static MetaButtonType
type_from_string (const gchar *str)
{
if (g_strcmp0 (str, "menu") == 0)
return META_BUTTON_TYPE_MENU;
else if (g_strcmp0 (str, "appmenu") == 0)
return META_BUTTON_TYPE_APPMENU;
else if (g_strcmp0 (str, "minimize") == 0)
return META_BUTTON_TYPE_MINIMIZE;
else if (g_strcmp0 (str, "maximize") == 0)
return META_BUTTON_TYPE_MAXIMIZE;
else if (g_strcmp0 (str, "close") == 0)
return META_BUTTON_TYPE_CLOSE;
else if (g_strcmp0 (str, "shade") == 0)
return META_BUTTON_TYPE_SHADE;
else if (g_strcmp0 (str, "unshade") == 0)
return META_BUTTON_TYPE_UNSHADE;
else if (g_strcmp0 (str, "above") == 0)
return META_BUTTON_TYPE_ABOVE;
else if (g_strcmp0 (str, "unabove") == 0)
return META_BUTTON_TYPE_UNABOVE;
else if (g_strcmp0 (str, "stick") == 0)
return META_BUTTON_TYPE_STICK;
else if (g_strcmp0 (str, "unstick") == 0)
return META_BUTTON_TYPE_UNSTICK;
else if (g_strcmp0 (str, "spacer") == 0)
return META_BUTTON_TYPE_SPACER;
return META_BUTTON_TYPE_LAST;
}
static MetaButtonType
get_opposite_type (MetaButtonType type)
{
switch (type)
{
case META_BUTTON_TYPE_SHADE:
return META_BUTTON_TYPE_UNSHADE;
case META_BUTTON_TYPE_UNSHADE:
return META_BUTTON_TYPE_SHADE;
case META_BUTTON_TYPE_ABOVE:
return META_BUTTON_TYPE_UNABOVE;
case META_BUTTON_TYPE_UNABOVE:
return META_BUTTON_TYPE_ABOVE;
case META_BUTTON_TYPE_STICK:
return META_BUTTON_TYPE_UNSTICK;
case META_BUTTON_TYPE_UNSTICK:
return META_BUTTON_TYPE_STICK;
case META_BUTTON_TYPE_MENU:
case META_BUTTON_TYPE_APPMENU:
case META_BUTTON_TYPE_MINIMIZE:
case META_BUTTON_TYPE_MAXIMIZE:
case META_BUTTON_TYPE_CLOSE:
case META_BUTTON_TYPE_SPACER:
case META_BUTTON_TYPE_LAST:
default:
break;
}
return META_BUTTON_TYPE_LAST;
}
static MetaButton *
string_to_buttons (const gchar *str,
gint *n_buttons)
{
gchar **buttons;
MetaButton *retval;
gint index;
gint i;
*n_buttons = 0;
if (str == NULL)
return NULL;
buttons = g_strsplit (str, ",", -1);
for (i = 0; buttons[i] != NULL; i++)
{
MetaButtonType type;
type = type_from_string (buttons[i]);
if (type != META_BUTTON_TYPE_LAST)
{
if (get_opposite_type (type) != META_BUTTON_TYPE_LAST)
*n_buttons += 2;
else
*n_buttons += 1;
}
else
{
g_debug ("Ignoring unknown button name - '%s'", buttons[i]);
}
}
retval = g_new0 (MetaButton, *n_buttons);
index = 0;
for (i = 0; buttons[i] != NULL; i++)
{
MetaButtonType type;
type = type_from_string (buttons[i]);
if (type != META_BUTTON_TYPE_LAST)
{
GdkRectangle empty;
MetaButton tmp;
empty.x = 0;
empty.y = 0;
empty.width = 0;
empty.height = 0;
tmp.type = type;
tmp.state = META_BUTTON_STATE_NORMAL;
tmp.rect.visible = empty;
tmp.rect.clickable = empty;
tmp.visible = TRUE;
retval[index++] = tmp;
type = get_opposite_type (type);
if (type != META_BUTTON_TYPE_LAST)
{
tmp.type = type;
retval[index++] = tmp;
}
}
}
g_strfreev (buttons);
return retval;
}
MetaButtonLayout *
meta_button_layout_new (const gchar *str,
gboolean invert)
{
MetaButtonLayout *layout;
gchar **sides;
const gchar *buttons;
gint n_buttons;
layout = g_new0 (MetaButtonLayout, 1);
sides = g_strsplit (str, ":", 2);
buttons = sides[0];
layout->left_buttons = string_to_buttons (buttons, &n_buttons);
layout->n_left_buttons = n_buttons;
buttons = sides[0] != NULL ? sides[1] : NULL;
layout->right_buttons = string_to_buttons (buttons, &n_buttons);
layout->n_right_buttons = n_buttons;
g_strfreev (sides);
if (invert)
{
MetaButtonLayout *rtl_layout;
gint i;
rtl_layout = g_new0 (MetaButtonLayout, 1);
rtl_layout->left_buttons = g_new0 (MetaButton, layout->n_right_buttons);
for (i = 0; i < layout->n_right_buttons; i++)
rtl_layout->left_buttons[i] = layout->right_buttons[layout->n_right_buttons - i - 1];
rtl_layout->n_left_buttons = layout->n_right_buttons;
rtl_layout->right_buttons = g_new0 (MetaButton, layout->n_left_buttons);
for (i = 0; i < layout->n_left_buttons; i++)
rtl_layout->right_buttons[i] = layout->left_buttons[layout->n_left_buttons - i - 1];
rtl_layout->n_right_buttons = layout->n_left_buttons;
meta_button_layout_free (layout);
return rtl_layout;
}
return layout;
}
void
meta_button_layout_free (MetaButtonLayout *layout)
{
g_free (layout->left_buttons);
g_free (layout->right_buttons);
g_free (layout);
}