/* * 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 . */ #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); }