|
Packit |
5e0819 |
/*
|
|
Packit |
5e0819 |
* Copyright (C) 2016 Alberts Muktupāvels
|
|
Packit |
5e0819 |
*
|
|
Packit |
5e0819 |
* This program is free software: you can redistribute it and/or modify
|
|
Packit |
5e0819 |
* it under the terms of the GNU General Public License as published by
|
|
Packit |
5e0819 |
* the Free Software Foundation, either version 2 of the License, or
|
|
Packit |
5e0819 |
* (at your option) any later version.
|
|
Packit |
5e0819 |
*
|
|
Packit |
5e0819 |
* This program is distributed in the hope that it will be useful,
|
|
Packit |
5e0819 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
5e0819 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit |
5e0819 |
* GNU General Public License for more details.
|
|
Packit |
5e0819 |
*
|
|
Packit |
5e0819 |
* You should have received a copy of the GNU General Public License
|
|
Packit |
5e0819 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit |
5e0819 |
*/
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
#include "config.h"
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
#include <gtk/gtk.h>
|
|
Packit |
5e0819 |
#include <stdlib.h>
|
|
Packit |
5e0819 |
#include <string.h>
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
#include "meta-rectangle-private.h"
|
|
Packit |
5e0819 |
#include "meta-frame-layout-private.h"
|
|
Packit |
5e0819 |
#include "meta-frame-style-private.h"
|
|
Packit |
5e0819 |
#include "meta-theme-gtk-private.h"
|
|
Packit |
5e0819 |
#include "meta-theme.h"
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
struct _MetaThemeGtk
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaThemeImpl parent;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
MetaFrameStyle *styles[META_FRAME_TYPE_LAST];
|
|
Packit |
5e0819 |
};
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
G_DEFINE_TYPE (MetaThemeGtk, meta_theme_gtk, META_TYPE_THEME_IMPL)
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
meta_theme_gtk_dispose (GObject *object)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaThemeGtk *gtk;
|
|
Packit |
5e0819 |
gint i;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk = META_THEME_GTK (object);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = 0; i < META_FRAME_TYPE_LAST; i++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
if (gtk->styles[i] != NULL)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
meta_frame_style_unref (gtk->styles[i]);
|
|
Packit |
5e0819 |
gtk->styles[i] = NULL;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
G_OBJECT_CLASS (meta_theme_gtk_parent_class)->dispose (object);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static gboolean
|
|
Packit |
5e0819 |
meta_theme_gtk_load (MetaThemeImpl *impl,
|
|
Packit |
5e0819 |
const gchar *name,
|
|
Packit |
5e0819 |
GError **error)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
return TRUE;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
get_margin (GtkStyleContext *style,
|
|
Packit |
5e0819 |
GtkBorder *border)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
GtkStateFlags state;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
state = gtk_style_context_get_state (style);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk_style_context_get_margin (style, state, border);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
get_padding_and_border (GtkStyleContext *style,
|
|
Packit |
5e0819 |
GtkBorder *border)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
GtkBorder tmp;
|
|
Packit |
5e0819 |
GtkStateFlags state = gtk_style_context_get_state (style);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk_style_context_get_border (style, state, border);
|
|
Packit |
5e0819 |
gtk_style_context_get_padding (style, state, &tmp);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
border->left += tmp.left;
|
|
Packit |
5e0819 |
border->top += tmp.top;
|
|
Packit |
5e0819 |
border->right += tmp.right;
|
|
Packit |
5e0819 |
border->bottom += tmp.bottom;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
get_min_size (GtkStyleContext *style,
|
|
Packit |
5e0819 |
GtkRequisition *requisition)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
|
Packit |
5e0819 |
"min-width", &requisition->width,
|
|
Packit |
5e0819 |
"min-height", &requisition->height,
|
|
Packit |
5e0819 |
NULL);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
get_shadow_extents (GtkStyleContext *style,
|
|
Packit |
5e0819 |
GtkBorder *border)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
GdkRectangle clip;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk_render_background_get_clip (style, 0, 0, 0, 0, &clip);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
border->left = abs (clip.x);
|
|
Packit |
5e0819 |
border->top = abs (clip.y);
|
|
Packit |
5e0819 |
border->right = clip.width - border->left;
|
|
Packit |
5e0819 |
border->bottom = clip.height - border->top;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
frame_layout_sync_with_style (MetaFrameLayout *layout,
|
|
Packit |
5e0819 |
MetaStyleInfo *style_info,
|
|
Packit |
5e0819 |
gboolean composited,
|
|
Packit |
5e0819 |
MetaFrameFlags flags)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
GtkStyleContext *style;
|
|
Packit |
5e0819 |
GtkBorder border;
|
|
Packit |
5e0819 |
GtkRequisition requisition;
|
|
Packit |
5e0819 |
int border_radius, max_radius;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
meta_style_info_set_flags (style_info, flags);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
style = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_DECORATION);
|
|
Packit |
5e0819 |
get_padding_and_border (style, &layout->gtk.frame_border);
|
|
Packit |
5e0819 |
scale_border (&layout->gtk.frame_border, layout->title_scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (composited)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
/* With compositing manager: margin is resize area */
|
|
Packit |
5e0819 |
get_margin (style, &layout->invisible_resize_border);
|
|
Packit |
5e0819 |
get_shadow_extents (style, &layout->gtk.shadow_border);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk_style_context_get (style, gtk_style_context_get_state (style),
|
|
Packit |
5e0819 |
"border-radius", &border_radius,
|
|
Packit |
5e0819 |
NULL);
|
|
Packit |
5e0819 |
/* GTK+ currently does not allow us to look up radii of individual
|
|
Packit |
5e0819 |
* corners; however we don't clip the client area, so with the
|
|
Packit |
5e0819 |
* current trend of using small/no visible frame borders, most
|
|
Packit |
5e0819 |
* themes should work fine with this.
|
|
Packit |
5e0819 |
*/
|
|
Packit |
5e0819 |
layout->top_left_corner_rounded_radius = border_radius;
|
|
Packit |
5e0819 |
layout->top_right_corner_rounded_radius = border_radius;
|
|
Packit |
5e0819 |
max_radius = MIN (layout->gtk.frame_border.bottom, layout->gtk.frame_border.left);
|
|
Packit |
5e0819 |
layout->bottom_left_corner_rounded_radius = MAX (border_radius, max_radius);
|
|
Packit |
5e0819 |
max_radius = MIN (layout->gtk.frame_border.bottom, layout->gtk.frame_border.left);
|
|
Packit |
5e0819 |
layout->bottom_right_corner_rounded_radius = MAX (border_radius, max_radius);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
/* Without compositing manager we can not have invisible border */
|
|
Packit |
5e0819 |
layout->invisible_resize_border.top = 0;
|
|
Packit |
5e0819 |
layout->invisible_resize_border.bottom = 0;
|
|
Packit |
5e0819 |
layout->invisible_resize_border.left = 0;
|
|
Packit |
5e0819 |
layout->invisible_resize_border.right = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
layout->gtk.shadow_border.top = 0;
|
|
Packit |
5e0819 |
layout->gtk.shadow_border.bottom = 0;
|
|
Packit |
5e0819 |
layout->gtk.shadow_border.left = 0;
|
|
Packit |
5e0819 |
layout->gtk.shadow_border.right = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
layout->top_left_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
layout->top_right_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
layout->bottom_left_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
layout->bottom_right_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Without compositing manager: margin is part of border */
|
|
Packit |
5e0819 |
get_margin (style, &border);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
layout->gtk.frame_border.left += border.left;
|
|
Packit |
5e0819 |
layout->gtk.frame_border.right += border.right;
|
|
Packit |
5e0819 |
layout->gtk.frame_border.top += border.top;
|
|
Packit |
5e0819 |
layout->gtk.frame_border.bottom += border.bottom;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (layout->hide_buttons)
|
|
Packit |
5e0819 |
layout->gtk.icon_size = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (!layout->has_title && layout->hide_buttons)
|
|
Packit |
5e0819 |
return; /* border-only - be done */
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
style = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_TITLEBAR);
|
|
Packit |
5e0819 |
get_min_size (style, &layout->gtk.titlebar_min_size);
|
|
Packit |
5e0819 |
get_padding_and_border (style, &layout->gtk.titlebar_border);
|
|
Packit |
5e0819 |
scale_border (&layout->gtk.titlebar_border, layout->title_scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
style = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_TITLE);
|
|
Packit |
5e0819 |
get_margin (style, &layout->gtk.title_margin);
|
|
Packit |
5e0819 |
scale_border (&layout->gtk.title_margin, layout->title_scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
style = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_BUTTON);
|
|
Packit |
5e0819 |
get_min_size (style, &layout->gtk.button_min_size);
|
|
Packit |
5e0819 |
get_padding_and_border (style, &layout->button_border);
|
|
Packit |
5e0819 |
scale_border (&layout->button_border, layout->title_scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
get_margin (style, &layout->gtk.button_margin);
|
|
Packit |
5e0819 |
scale_border (&layout->gtk.button_margin, layout->title_scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
style = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_IMAGE);
|
|
Packit |
5e0819 |
get_min_size (style, &requisition);
|
|
Packit |
5e0819 |
get_padding_and_border (style, &border);
|
|
Packit |
5e0819 |
scale_border (&border, layout->title_scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
layout->button_border.left += border.left;
|
|
Packit |
5e0819 |
layout->button_border.right += border.right;
|
|
Packit |
5e0819 |
layout->button_border.top += border.top;
|
|
Packit |
5e0819 |
layout->button_border.bottom += border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
get_margin (style, &border);
|
|
Packit |
5e0819 |
layout->button_border.left += border.left;
|
|
Packit |
5e0819 |
layout->button_border.right += border.right;
|
|
Packit |
5e0819 |
layout->button_border.top += border.top;
|
|
Packit |
5e0819 |
layout->button_border.bottom += border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
layout->gtk.button_min_size.width = MAX (layout->gtk.button_min_size.width,
|
|
Packit |
5e0819 |
requisition.width);
|
|
Packit |
5e0819 |
layout->gtk.button_min_size.height = MAX (layout->gtk.button_min_size.height,
|
|
Packit |
5e0819 |
requisition.height);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static MetaFrameStyle *
|
|
Packit |
5e0819 |
meta_theme_gtk_get_frame_style (MetaThemeImpl *impl,
|
|
Packit |
5e0819 |
MetaFrameType type,
|
|
Packit |
5e0819 |
MetaFrameFlags flags)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaThemeGtk *gtk;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk = META_THEME_GTK (impl);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
return gtk->styles[type];
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
meta_theme_gtk_get_frame_borders (MetaThemeImpl *impl,
|
|
Packit |
5e0819 |
MetaFrameLayout *layout,
|
|
Packit |
5e0819 |
MetaStyleInfo *style_info,
|
|
Packit |
5e0819 |
gint text_height,
|
|
Packit |
5e0819 |
MetaFrameFlags flags,
|
|
Packit |
5e0819 |
MetaFrameType type,
|
|
Packit |
5e0819 |
MetaFrameBorders *borders)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
gboolean composited;
|
|
Packit |
5e0819 |
gint scale;
|
|
Packit |
5e0819 |
gint title_height;
|
|
Packit |
5e0819 |
gint buttons_height;
|
|
Packit |
5e0819 |
gint content_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
composited = meta_theme_impl_get_composited (impl);
|
|
Packit |
5e0819 |
frame_layout_sync_with_style (layout, style_info, composited, flags);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
meta_frame_borders_clear (borders);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* For a full-screen window, we don't have any borders, visible or not. */
|
|
Packit |
5e0819 |
if (flags & META_FRAME_FULLSCREEN)
|
|
Packit |
5e0819 |
return;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
g_return_if_fail (layout != NULL);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (!layout->has_title)
|
|
Packit |
5e0819 |
text_height = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Scale geometry for HiDPI, see comment in meta_theme_gtk_draw_frame () */
|
|
Packit |
5e0819 |
scale = meta_theme_impl_get_scale (impl);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
title_height = layout->gtk.title_margin.top +
|
|
Packit |
5e0819 |
text_height / scale +
|
|
Packit |
5e0819 |
layout->gtk.title_margin.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
buttons_height = MAX ((gint) layout->gtk.icon_size, layout->gtk.button_min_size.height) +
|
|
Packit |
5e0819 |
layout->gtk.button_margin.top + layout->button_border.top +
|
|
Packit |
5e0819 |
layout->gtk.button_margin.bottom + layout->button_border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
content_height = MAX (title_height, buttons_height);
|
|
Packit |
5e0819 |
content_height = MAX (content_height, layout->gtk.titlebar_min_size.height) +
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.top +
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
borders->visible.top = layout->gtk.frame_border.top + content_height;
|
|
Packit |
5e0819 |
borders->visible.left = layout->gtk.frame_border.left;
|
|
Packit |
5e0819 |
borders->visible.right = layout->gtk.frame_border.right;
|
|
Packit |
5e0819 |
borders->visible.bottom = layout->gtk.frame_border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
borders->shadow = layout->gtk.shadow_border;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
borders->resize.left = layout->invisible_resize_border.left;
|
|
Packit |
5e0819 |
borders->resize.right = layout->invisible_resize_border.right;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
borders->resize.bottom = layout->invisible_resize_border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (type != META_FRAME_TYPE_ATTACHED)
|
|
Packit |
5e0819 |
borders->resize.top = layout->invisible_resize_border.top;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
borders->invisible.left = MAX (borders->shadow.left, borders->resize.left);
|
|
Packit |
5e0819 |
borders->invisible.right = MAX (borders->shadow.right, borders->resize.right);
|
|
Packit |
5e0819 |
borders->invisible.bottom = MAX (borders->shadow.bottom, borders->resize.bottom);
|
|
Packit |
5e0819 |
borders->invisible.top = MAX (borders->shadow.top, borders->resize.top);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
borders->total.left = borders->invisible.left + borders->visible.left;
|
|
Packit |
5e0819 |
borders->total.right = borders->invisible.right + borders->visible.right;
|
|
Packit |
5e0819 |
borders->total.bottom = borders->invisible.bottom + borders->visible.bottom;
|
|
Packit |
5e0819 |
borders->total.top = borders->invisible.top + borders->visible.top;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
scale_border (&borders->visible, scale);
|
|
Packit |
5e0819 |
scale_border (&borders->shadow, scale);
|
|
Packit |
5e0819 |
scale_border (&borders->resize, scale);
|
|
Packit |
5e0819 |
scale_border (&borders->invisible, scale);
|
|
Packit |
5e0819 |
scale_border (&borders->total, scale);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
meta_theme_gtk_calc_geometry (MetaThemeImpl *impl,
|
|
Packit |
5e0819 |
MetaFrameLayout *layout,
|
|
Packit |
5e0819 |
MetaStyleInfo *style_info,
|
|
Packit |
5e0819 |
gint text_height,
|
|
Packit |
5e0819 |
MetaFrameFlags flags,
|
|
Packit |
5e0819 |
gint client_width,
|
|
Packit |
5e0819 |
gint client_height,
|
|
Packit |
5e0819 |
MetaButtonLayout *button_layout,
|
|
Packit |
5e0819 |
MetaFrameType type,
|
|
Packit |
5e0819 |
MetaFrameGeometry *fgeom)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaFrameBorders borders;
|
|
Packit |
5e0819 |
int i, n_left, n_right, n_left_spacers, n_right_spacers;
|
|
Packit |
5e0819 |
int x;
|
|
Packit |
5e0819 |
int button_y;
|
|
Packit |
5e0819 |
int title_right_edge;
|
|
Packit |
5e0819 |
int width, height;
|
|
Packit |
5e0819 |
int scale;
|
|
Packit |
5e0819 |
int content_height;
|
|
Packit |
5e0819 |
int button_width, button_height;
|
|
Packit |
5e0819 |
int min_size_for_rounding;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
META_THEME_IMPL_GET_CLASS (impl)->get_frame_borders (impl, layout,
|
|
Packit |
5e0819 |
style_info, text_height,
|
|
Packit |
5e0819 |
flags, type, &borders);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
fgeom->borders = borders;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
width = client_width + borders.total.left + borders.total.right;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
height = borders.total.top + borders.total.bottom;
|
|
Packit |
5e0819 |
if (!(flags & META_FRAME_SHADED))
|
|
Packit |
5e0819 |
height += client_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
fgeom->width = width;
|
|
Packit |
5e0819 |
fgeom->height = height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Scale geometry for HiDPI, see comment in meta_theme_gtk_draw_frame () */
|
|
Packit |
5e0819 |
scale = meta_theme_impl_get_scale (impl);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
content_height = borders.visible.top - layout->gtk.frame_border.top * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button_width = MAX ((gint) layout->gtk.icon_size, layout->gtk.button_min_size.width) +
|
|
Packit |
5e0819 |
layout->button_border.left + layout->button_border.right;
|
|
Packit |
5e0819 |
button_height = MAX ((gint) layout->gtk.icon_size, layout->gtk.button_min_size.height) +
|
|
Packit |
5e0819 |
layout->button_border.top + layout->button_border.bottom;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button_width *= scale;
|
|
Packit |
5e0819 |
button_height *= scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
n_left = 0;
|
|
Packit |
5e0819 |
n_right = 0;
|
|
Packit |
5e0819 |
n_left_spacers = 0;
|
|
Packit |
5e0819 |
n_right_spacers = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (!layout->hide_buttons)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaButton *button;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = 0; i < button_layout->n_left_buttons; i++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
button = &button_layout->left_buttons[i];
|
|
Packit |
5e0819 |
button->visible = is_button_visible (button, flags);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->visible)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
if (button->type != META_BUTTON_TYPE_SPACER)
|
|
Packit |
5e0819 |
n_left++;
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
n_left_spacers++;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = 0; i < button_layout->n_right_buttons; i++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
button = &button_layout->right_buttons[i];
|
|
Packit |
5e0819 |
button->visible = is_button_visible (button, flags);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->visible)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
if (button->type != META_BUTTON_TYPE_SPACER)
|
|
Packit |
5e0819 |
n_right++;
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
n_right_spacers++;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
for (i = 0; i < button_layout->n_left_buttons; i++)
|
|
Packit |
5e0819 |
button_layout->left_buttons[i].visible = FALSE;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = 0; i < button_layout->n_right_buttons; i++)
|
|
Packit |
5e0819 |
button_layout->right_buttons[i].visible = FALSE;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Be sure buttons fit */
|
|
Packit |
5e0819 |
while (n_left > 0 || n_right > 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
int space_used_by_buttons;
|
|
Packit |
5e0819 |
int space_available;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
space_available = fgeom->width -
|
|
Packit |
5e0819 |
borders.total.left -
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.left * scale -
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.right * scale -
|
|
Packit |
5e0819 |
borders.total.right;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
space_used_by_buttons = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
space_used_by_buttons += layout->gtk.button_margin.left * scale * n_left;
|
|
Packit |
5e0819 |
space_used_by_buttons += button_width * n_left;
|
|
Packit |
5e0819 |
space_used_by_buttons += layout->gtk.button_margin.right * scale * n_left;
|
|
Packit |
5e0819 |
space_used_by_buttons += (button_width * 0.75) * n_left_spacers;
|
|
Packit |
5e0819 |
space_used_by_buttons += layout->gtk.titlebar_spacing * scale * MAX (n_left - 1, 0);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
space_used_by_buttons += layout->gtk.button_margin.left * scale * n_right;
|
|
Packit |
5e0819 |
space_used_by_buttons += button_width * n_right;
|
|
Packit |
5e0819 |
space_used_by_buttons += layout->gtk.button_margin.right * scale * n_right;
|
|
Packit |
5e0819 |
space_used_by_buttons += (button_width * 0.75) * n_right_spacers;
|
|
Packit |
5e0819 |
space_used_by_buttons += layout->gtk.titlebar_spacing * scale * MAX (n_right - 1, 0);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (space_used_by_buttons <= space_available)
|
|
Packit |
5e0819 |
break; /* Everything fits, bail out */
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* First try to remove separators */
|
|
Packit |
5e0819 |
if (n_left_spacers > 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
if (strip_button (button_layout->left_buttons,
|
|
Packit |
5e0819 |
button_layout->n_left_buttons,
|
|
Packit |
5e0819 |
META_BUTTON_TYPE_SPACER))
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
n_left_spacers--;
|
|
Packit |
5e0819 |
continue;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
g_assert_not_reached ();
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else if (n_right_spacers > 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
if (strip_button (button_layout->right_buttons,
|
|
Packit |
5e0819 |
button_layout->n_right_buttons,
|
|
Packit |
5e0819 |
META_BUTTON_TYPE_SPACER))
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
n_right_spacers--;
|
|
Packit |
5e0819 |
continue;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
g_assert_not_reached ();
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Otherwise we need to shave out a button. Shave
|
|
Packit |
5e0819 |
* above, stick, shade, min, max, close, then menu (menu is most useful);
|
|
Packit |
5e0819 |
* prefer the default button locations.
|
|
Packit |
5e0819 |
*/
|
|
Packit |
5e0819 |
if (strip_buttons (button_layout, &n_left, &n_right))
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
continue;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
g_error ("Could not find a button to strip. n_left = %d n_right = %d",
|
|
Packit |
5e0819 |
n_left, n_right);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* center buttons vertically */
|
|
Packit |
5e0819 |
button_y = borders.invisible.top + layout->gtk.frame_border.top * scale +
|
|
Packit |
5e0819 |
(content_height - button_height) / 2;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* right edge of farthest-right button */
|
|
Packit |
5e0819 |
x = width - borders.invisible.right - layout->gtk.frame_border.right * scale -
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.right * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = button_layout->n_right_buttons - 1; i >= 0; i--)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaButton *button;
|
|
Packit |
5e0819 |
GdkRectangle rect;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button = &button_layout->right_buttons[i];
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->visible == FALSE)
|
|
Packit |
5e0819 |
continue;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* if we go negative, leave the buttons we don't get to as 0 - width */
|
|
Packit |
5e0819 |
if (x < 0)
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
x -= layout->gtk.button_margin.right * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
rect.y = button_y;
|
|
Packit |
5e0819 |
rect.width = button_width;
|
|
Packit |
5e0819 |
rect.height = button_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->type == META_BUTTON_TYPE_SPACER)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
rect.x = x - button_width * 0.75;
|
|
Packit |
5e0819 |
rect.width *= 0.75;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
rect.x = x - button_width;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button->rect.visible = rect;
|
|
Packit |
5e0819 |
button->rect.clickable = rect;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if ((flags & META_FRAME_MAXIMIZED || flags & META_FRAME_TILED_RIGHT) &&
|
|
Packit |
5e0819 |
i == button_layout->n_right_buttons - 1)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
gint extra_width;
|
|
Packit |
5e0819 |
gint extra_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
extra_width = layout->gtk.button_margin.right * scale +
|
|
Packit |
5e0819 |
layout->gtk.frame_border.right * scale +
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.right * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* FIXME: */
|
|
Packit |
5e0819 |
extra_height = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button->rect.clickable.y -= extra_height;
|
|
Packit |
5e0819 |
button->rect.clickable.width += extra_width;
|
|
Packit |
5e0819 |
button->rect.clickable.height += extra_height;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
x = rect.x - layout->gtk.button_margin.left * scale;
|
|
Packit |
5e0819 |
x -= layout->gtk.titlebar_spacing * scale;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* save right edge of titlebar for later use */
|
|
Packit |
5e0819 |
title_right_edge = x;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Now x changes to be position from the left and we go through
|
|
Packit |
5e0819 |
* the left-side buttons
|
|
Packit |
5e0819 |
*/
|
|
Packit |
5e0819 |
x = borders.invisible.left + layout->gtk.frame_border.left * scale +
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.left * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = 0; i < button_layout->n_left_buttons; i++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaButton *button;
|
|
Packit |
5e0819 |
GdkRectangle rect;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button = &button_layout->left_buttons[i];
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->visible == FALSE)
|
|
Packit |
5e0819 |
continue;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
rect.x = x + layout->gtk.button_margin.left * scale;
|
|
Packit |
5e0819 |
rect.y = button_y;
|
|
Packit |
5e0819 |
rect.width = button_width;
|
|
Packit |
5e0819 |
rect.height = button_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->type == META_BUTTON_TYPE_SPACER)
|
|
Packit |
5e0819 |
rect.width *= 0.75;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button->rect.visible = rect;
|
|
Packit |
5e0819 |
button->rect.clickable = rect;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if ((flags & META_FRAME_MAXIMIZED || flags & META_FRAME_TILED_LEFT) &&
|
|
Packit |
5e0819 |
i == 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
gint extra_width;
|
|
Packit |
5e0819 |
gint extra_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
extra_width = layout->gtk.button_margin.left * scale +
|
|
Packit |
5e0819 |
layout->gtk.frame_border.left * scale +
|
|
Packit |
5e0819 |
layout->gtk.titlebar_border.left * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* FIXME: */
|
|
Packit |
5e0819 |
extra_height = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button->rect.clickable.x -= extra_width;
|
|
Packit |
5e0819 |
button->rect.clickable.y -= extra_height;
|
|
Packit |
5e0819 |
button->rect.clickable.width += extra_width;
|
|
Packit |
5e0819 |
button->rect.clickable.height += extra_height;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
x = rect.x + rect.width + layout->gtk.button_margin.right * scale;
|
|
Packit |
5e0819 |
x += layout->gtk.titlebar_spacing * scale;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Center vertically in the available content area */
|
|
Packit |
5e0819 |
fgeom->title_rect.x = x;
|
|
Packit |
5e0819 |
fgeom->title_rect.y = borders.invisible.top + layout->gtk.frame_border.top * scale +
|
|
Packit |
5e0819 |
(content_height - text_height) / 2;
|
|
Packit |
5e0819 |
fgeom->title_rect.width = title_right_edge - fgeom->title_rect.x;
|
|
Packit |
5e0819 |
fgeom->title_rect.height = text_height;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Nuke title if it won't fit */
|
|
Packit |
5e0819 |
if (fgeom->title_rect.width < 0 ||
|
|
Packit |
5e0819 |
fgeom->title_rect.height < 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
fgeom->title_rect.width = 0;
|
|
Packit |
5e0819 |
fgeom->title_rect.height = 0;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (flags & META_FRAME_SHADED)
|
|
Packit |
5e0819 |
min_size_for_rounding = 0;
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
min_size_for_rounding = 5 * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
fgeom->top_left_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
fgeom->top_right_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
fgeom->bottom_left_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
fgeom->bottom_right_corner_rounded_radius = 0;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (borders.visible.top + borders.visible.left >= min_size_for_rounding)
|
|
Packit |
5e0819 |
fgeom->top_left_corner_rounded_radius = layout->top_left_corner_rounded_radius * scale;
|
|
Packit |
5e0819 |
if (borders.visible.top + borders.visible.right >= min_size_for_rounding)
|
|
Packit |
5e0819 |
fgeom->top_right_corner_rounded_radius = layout->top_right_corner_rounded_radius * scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (borders.visible.bottom + borders.visible.left >= min_size_for_rounding)
|
|
Packit |
5e0819 |
fgeom->bottom_left_corner_rounded_radius = layout->bottom_left_corner_rounded_radius * scale;
|
|
Packit |
5e0819 |
if (borders.visible.bottom + borders.visible.right >= min_size_for_rounding)
|
|
Packit |
5e0819 |
fgeom->bottom_right_corner_rounded_radius = layout->bottom_right_corner_rounded_radius * scale;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static const char *
|
|
Packit |
5e0819 |
get_class_from_button_type (MetaButtonType type)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
if (type == META_BUTTON_TYPE_CLOSE)
|
|
Packit |
5e0819 |
return "close";
|
|
Packit |
5e0819 |
else if (type == META_BUTTON_TYPE_MAXIMIZE)
|
|
Packit |
5e0819 |
return "maximize";
|
|
Packit |
5e0819 |
else if (type == META_BUTTON_TYPE_MINIMIZE)
|
|
Packit |
5e0819 |
return "minimize";
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
return NULL;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
meta_theme_gtk_draw_frame (MetaThemeImpl *impl,
|
|
Packit |
5e0819 |
MetaFrameStyle *style,
|
|
Packit |
5e0819 |
MetaStyleInfo *style_info,
|
|
Packit |
5e0819 |
cairo_t *cr,
|
|
Packit |
5e0819 |
const MetaFrameGeometry *fgeom,
|
|
Packit |
5e0819 |
PangoLayout *title_layout,
|
|
Packit |
5e0819 |
MetaFrameFlags flags,
|
|
Packit |
5e0819 |
const MetaButtonLayout *button_layout,
|
|
Packit |
5e0819 |
GdkPixbuf *mini_icon,
|
|
Packit |
5e0819 |
GdkPixbuf *icon)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
gdouble scale;
|
|
Packit |
5e0819 |
GtkStyleContext *context;
|
|
Packit |
5e0819 |
GtkStateFlags state;
|
|
Packit |
5e0819 |
MetaRectangleDouble visible_rect;
|
|
Packit |
5e0819 |
MetaRectangleDouble titlebar_rect;
|
|
Packit |
5e0819 |
const MetaFrameBorders *borders;
|
|
Packit |
5e0819 |
gint side;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* We opt out of GTK+ HiDPI handling, so we have to do the scaling
|
|
Packit |
5e0819 |
* ourselves; the nitty-gritty is a bit confusing, so here is an overview:
|
|
Packit |
5e0819 |
* - the values in MetaFrameLayout are always as they appear in the theme,
|
|
Packit |
5e0819 |
* i.e. unscaled
|
|
Packit |
5e0819 |
* - calculated values (borders, MetaFrameGeometry) include the scale - as
|
|
Packit |
5e0819 |
* the geometry is comprised of scaled decorations and the client size
|
|
Packit |
5e0819 |
* which we must not scale, we don't have another option
|
|
Packit |
5e0819 |
* - for drawing, we scale the canvas to have GTK+ render elements (borders,
|
|
Packit |
5e0819 |
* radii, ...) at the correct scale - as a result, we have to "unscale"
|
|
Packit |
5e0819 |
* the geometry again to not apply the scaling twice
|
|
Packit |
5e0819 |
*/
|
|
Packit |
5e0819 |
scale = meta_theme_impl_get_scale (impl);
|
|
Packit |
5e0819 |
cairo_scale (cr, scale, scale);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
borders = &fgeom->borders;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
visible_rect.x = borders->invisible.left / scale;
|
|
Packit |
5e0819 |
visible_rect.y = borders->invisible.top / scale;
|
|
Packit |
5e0819 |
visible_rect.width = (fgeom->width - borders->invisible.left - borders->invisible.right) / scale;
|
|
Packit |
5e0819 |
visible_rect.height = (fgeom->height - borders->invisible.top - borders->invisible.bottom) / scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
meta_style_info_set_flags (style_info, flags);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
context = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_DECORATION);
|
|
Packit |
5e0819 |
gtk_render_background (context, cr,
|
|
Packit |
5e0819 |
visible_rect.x, visible_rect.y,
|
|
Packit |
5e0819 |
visible_rect.width, visible_rect.height);
|
|
Packit |
5e0819 |
gtk_render_frame (context, cr,
|
|
Packit |
5e0819 |
visible_rect.x, visible_rect.y,
|
|
Packit |
5e0819 |
visible_rect.width, visible_rect.height);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (flags & META_FRAME_FULLSCREEN)
|
|
Packit |
5e0819 |
return;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
titlebar_rect.x = visible_rect.x + borders->visible.left / scale;
|
|
Packit |
5e0819 |
titlebar_rect.y = visible_rect.y + style->layout->gtk.frame_border.top;
|
|
Packit |
5e0819 |
titlebar_rect.width = visible_rect.width - (borders->visible.left + borders->visible.right) / scale;
|
|
Packit |
5e0819 |
titlebar_rect.height = (borders->visible.top / scale) - style->layout->gtk.frame_border.top;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
context = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_TITLEBAR);
|
|
Packit |
5e0819 |
gtk_render_background (context, cr,
|
|
Packit |
5e0819 |
titlebar_rect.x, titlebar_rect.y,
|
|
Packit |
5e0819 |
titlebar_rect.width, titlebar_rect.height);
|
|
Packit |
5e0819 |
gtk_render_frame (context, cr,
|
|
Packit |
5e0819 |
titlebar_rect.x, titlebar_rect.y,
|
|
Packit |
5e0819 |
titlebar_rect.width, titlebar_rect.height);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (style->layout->has_title && title_layout)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
PangoRectangle logical;
|
|
Packit |
5e0819 |
gdouble text_width, x, y;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
pango_layout_set_width (title_layout, -1);
|
|
Packit |
5e0819 |
pango_layout_get_pixel_extents (title_layout, NULL, &logical);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
text_width = MIN(fgeom->title_rect.width / scale, logical.width);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (text_width < logical.width)
|
|
Packit |
5e0819 |
pango_layout_set_width (title_layout, PANGO_SCALE * text_width);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
/* Center within the frame if possible */
|
|
Packit |
5e0819 |
x = titlebar_rect.x + (titlebar_rect.width - text_width) / 2;
|
|
Packit |
5e0819 |
y = titlebar_rect.y + (titlebar_rect.height - logical.height) / 2;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (x < fgeom->title_rect.x / scale)
|
|
Packit |
5e0819 |
x = fgeom->title_rect.x / scale;
|
|
Packit |
5e0819 |
else if (x + text_width > (fgeom->title_rect.x + fgeom->title_rect.width) / scale)
|
|
Packit |
5e0819 |
x = (fgeom->title_rect.x + fgeom->title_rect.width) / scale - text_width;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
cairo_save (cr);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
cairo_rectangle (cr,
|
|
Packit |
5e0819 |
fgeom->title_rect.x / scale,
|
|
Packit |
5e0819 |
fgeom->title_rect.y / scale,
|
|
Packit |
5e0819 |
fgeom->title_rect.width / scale,
|
|
Packit |
5e0819 |
fgeom->title_rect.height / scale);
|
|
Packit |
5e0819 |
cairo_clip (cr);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
context = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_TITLE);
|
|
Packit |
5e0819 |
gtk_render_layout (context, cr, x, y, title_layout);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
cairo_restore (cr);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
context = meta_style_info_get_style (style_info, META_STYLE_ELEMENT_BUTTON);
|
|
Packit |
5e0819 |
state = gtk_style_context_get_state (context);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (side = 0; side < 2; side++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaButton *buttons;
|
|
Packit |
5e0819 |
gint n_buttons;
|
|
Packit |
5e0819 |
gint i;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (side == 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
buttons = button_layout->left_buttons;
|
|
Packit |
5e0819 |
n_buttons = button_layout->n_left_buttons;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else if (side == 1)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
buttons = button_layout->right_buttons;
|
|
Packit |
5e0819 |
n_buttons = button_layout->n_right_buttons;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
g_assert_not_reached ();
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (i = 0; i < n_buttons; i++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaButton *button;
|
|
Packit |
5e0819 |
gdouble x;
|
|
Packit |
5e0819 |
gdouble y;
|
|
Packit |
5e0819 |
gdouble width;
|
|
Packit |
5e0819 |
gdouble height;
|
|
Packit |
5e0819 |
const gchar *button_class;
|
|
Packit |
5e0819 |
const gchar *icon_name;
|
|
Packit |
5e0819 |
GdkPixbuf *pixbuf;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button = &buttons[i];
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
x = button->rect.visible.x / scale;
|
|
Packit |
5e0819 |
y = button->rect.visible.y / scale;
|
|
Packit |
5e0819 |
width = button->rect.visible.width / scale;
|
|
Packit |
5e0819 |
height = button->rect.visible.height / scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (!button->visible || button->type == META_BUTTON_TYPE_SPACER ||
|
|
Packit |
5e0819 |
width <= 0 || height <= 0)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
continue;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
button_class = get_class_from_button_type (button->type);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button_class)
|
|
Packit |
5e0819 |
gtk_style_context_add_class (context, button_class);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button->state == META_BUTTON_STATE_PRELIGHT)
|
|
Packit |
5e0819 |
gtk_style_context_set_state (context, state | GTK_STATE_PRELIGHT);
|
|
Packit |
5e0819 |
else if (button->state == META_BUTTON_STATE_PRESSED)
|
|
Packit |
5e0819 |
gtk_style_context_set_state (context, state | GTK_STATE_ACTIVE);
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
gtk_style_context_set_state (context, state);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
cairo_save (cr);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk_render_background (context, cr, x, y, width, height);
|
|
Packit |
5e0819 |
gtk_render_frame (context, cr, x, y, width, height);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
icon_name = NULL;
|
|
Packit |
5e0819 |
pixbuf = NULL;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
switch (button->type)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_CLOSE:
|
|
Packit |
5e0819 |
icon_name = "window-close-symbolic";
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_MAXIMIZE:
|
|
Packit |
5e0819 |
if (flags & META_FRAME_MAXIMIZED)
|
|
Packit |
5e0819 |
icon_name = "window-restore-symbolic";
|
|
Packit |
5e0819 |
else
|
|
Packit |
5e0819 |
icon_name = "window-maximize-symbolic";
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_MINIMIZE:
|
|
Packit |
5e0819 |
icon_name = "window-minimize-symbolic";
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_MENU:
|
|
Packit |
5e0819 |
icon_name = "open-menu-symbolic";
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_APPMENU:
|
|
Packit |
5e0819 |
pixbuf = g_object_ref (mini_icon);
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_SHADE:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_ABOVE:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_STICK:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_UNSHADE:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_UNABOVE:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_UNSTICK:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_SPACER:
|
|
Packit |
5e0819 |
case META_BUTTON_TYPE_LAST:
|
|
Packit |
5e0819 |
default:
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (icon_name)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
GtkIconTheme *theme;
|
|
Packit |
5e0819 |
GtkIconInfo *info;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
theme = gtk_icon_theme_get_default ();
|
|
Packit |
5e0819 |
info = gtk_icon_theme_lookup_icon_for_scale (theme, icon_name,
|
|
Packit |
5e0819 |
style->layout->gtk.icon_size,
|
|
Packit |
5e0819 |
scale, 0);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
g_assert (pixbuf == NULL);
|
|
Packit |
5e0819 |
pixbuf = gtk_icon_info_load_symbolic_for_context (info, context, NULL, NULL);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (pixbuf)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
gdouble pwidth;
|
|
Packit |
5e0819 |
gdouble pheight;
|
|
Packit |
5e0819 |
gdouble px;
|
|
Packit |
5e0819 |
gdouble py;
|
|
Packit |
5e0819 |
gdouble scale_x;
|
|
Packit |
5e0819 |
gdouble scale_y;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
pwidth = gdk_pixbuf_get_width (pixbuf) / scale;
|
|
Packit |
5e0819 |
pheight = gdk_pixbuf_get_height (pixbuf) / scale;
|
|
Packit |
5e0819 |
px = x + (width - pwidth) / 2;
|
|
Packit |
5e0819 |
py = y + (height - pheight) / 2;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
scale_x = pwidth / style->layout->gtk.icon_size / scale;
|
|
Packit |
5e0819 |
scale_y = pheight / style->layout->gtk.icon_size / scale;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
cairo_translate (cr, px, py);
|
|
Packit |
5e0819 |
cairo_scale (cr, scale_x, scale_y);
|
|
Packit |
5e0819 |
gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
|
|
Packit |
5e0819 |
cairo_paint (cr);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
g_object_unref (pixbuf);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
cairo_restore (cr);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
if (button_class)
|
|
Packit |
5e0819 |
gtk_style_context_remove_class (context, button_class);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk_style_context_set_state (context, state);
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
meta_theme_gtk_class_init (MetaThemeGtkClass *gtk_class)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
GObjectClass *object_class;
|
|
Packit |
5e0819 |
MetaThemeImplClass *impl_class;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
object_class = G_OBJECT_CLASS (gtk_class);
|
|
Packit |
5e0819 |
impl_class = META_THEME_IMPL_CLASS (gtk_class);
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
object_class->dispose = meta_theme_gtk_dispose;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
impl_class->load = meta_theme_gtk_load;
|
|
Packit |
5e0819 |
impl_class->get_frame_style = meta_theme_gtk_get_frame_style;
|
|
Packit |
5e0819 |
impl_class->get_frame_borders = meta_theme_gtk_get_frame_borders;
|
|
Packit |
5e0819 |
impl_class->calc_geometry = meta_theme_gtk_calc_geometry;
|
|
Packit |
5e0819 |
impl_class->draw_frame = meta_theme_gtk_draw_frame;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
static void
|
|
Packit |
5e0819 |
meta_theme_gtk_init (MetaThemeGtk *gtk)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaFrameType type;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
for (type = 0; type < META_FRAME_TYPE_LAST; type++)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
MetaFrameStyle *style;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
style = meta_frame_style_new (NULL);
|
|
Packit |
5e0819 |
style->layout = meta_frame_layout_new ();
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
switch (type)
|
|
Packit |
5e0819 |
{
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_NORMAL:
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_DIALOG:
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_MODAL_DIALOG:
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_ATTACHED:
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_MENU:
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_UTILITY:
|
|
Packit |
5e0819 |
style->layout->title_scale = PANGO_SCALE_SMALL;
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_BORDER:
|
|
Packit |
5e0819 |
style->layout->has_title = FALSE;
|
|
Packit |
5e0819 |
style->layout->hide_buttons = TRUE;
|
|
Packit |
5e0819 |
break;
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
case META_FRAME_TYPE_LAST:
|
|
Packit |
5e0819 |
default:
|
|
Packit |
5e0819 |
g_assert_not_reached ();
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
|
|
Packit |
5e0819 |
gtk->styles[type] = style;
|
|
Packit |
5e0819 |
}
|
|
Packit |
5e0819 |
}
|