/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2001 Havoc Pennington
* Copyright (C) 2002 Red Hat, Inc.
* Copyright (C) 2005 Elijah Newren
*
* 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
#include
#include
#include "select-workspace.h"
#include "../core/frame-private.h"
#include "draw-workspace.h"
#define SELECT_OUTLINE_WIDTH 2
#define MINI_WORKSPACE_WIDTH 48
struct _MetaSelectWorkspacePrivate
{
MetaWorkspace *workspace;
gboolean selected;
};
G_DEFINE_TYPE_WITH_PRIVATE (MetaSelectWorkspace, meta_select_workspace, GTK_TYPE_DRAWING_AREA);
/**
* meta_convert_meta_to_wnck() converts a MetaWindow to a
* WnckWindowDisplayInfo window that is used to build a thumbnail of a
* workspace.
**/
static WnckWindowDisplayInfo
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
{
WnckWindowDisplayInfo wnck_window;
wnck_window.icon = window->icon;
wnck_window.mini_icon = window->mini_icon;
wnck_window.is_active = window->has_focus;
if (window->frame)
{
wnck_window.x = window->frame->rect.x;
wnck_window.y = window->frame->rect.y;
wnck_window.width = window->frame->rect.width;
wnck_window.height = window->frame->rect.height;
}
else
{
wnck_window.x = window->rect.x;
wnck_window.y = window->rect.y;
wnck_window.width = window->rect.width;
wnck_window.height = window->rect.height;
}
return wnck_window;
}
static gboolean
meta_select_workspace_draw (GtkWidget *widget,
cairo_t *cr)
{
MetaSelectWorkspace *select;
MetaWorkspace *workspace;
WnckWindowDisplayInfo *windows;
GtkAllocation allocation;
int i, n_windows;
GList *tmp, *list;
select = META_SELECT_WORKSPACE (widget);
workspace = select->priv->workspace;
list = meta_stack_list_windows (workspace->screen->stack, workspace);
n_windows = g_list_length (list);
windows = g_new (WnckWindowDisplayInfo, n_windows);
tmp = list;
i = 0;
while (tmp != NULL)
{
MetaWindow *window;
gboolean ignoreable_sticky;
window = tmp->data;
ignoreable_sticky = window->on_all_workspaces &&
workspace != workspace->screen->active_workspace;
if (window->skip_pager ||
!meta_window_showing_on_its_workspace (window) ||
window->unmaps_pending != NULL ||
ignoreable_sticky)
{
--n_windows;
}
else
{
windows[i] = meta_convert_meta_to_wnck (window, workspace->screen);
i++;
}
tmp = tmp->next;
}
g_list_free (list);
gtk_widget_get_allocation (widget, &allocation);
wnck_draw_workspace (widget,
cr,
SELECT_OUTLINE_WIDTH,
SELECT_OUTLINE_WIDTH,
allocation.width - SELECT_OUTLINE_WIDTH * 2,
allocation.height - SELECT_OUTLINE_WIDTH * 2,
workspace->screen->rect.width,
workspace->screen->rect.height,
NULL,
(workspace->screen->active_workspace == workspace),
windows,
n_windows);
g_free (windows);
if (select->priv->selected)
{
GtkStyleContext *context;
GdkRGBA color;
context = gtk_widget_get_style_context (widget);
gtk_style_context_set_state (context,
gtk_widget_get_state_flags (widget));
gtk_style_context_lookup_color (context, "color", &color);
cairo_set_line_width (cr, SELECT_OUTLINE_WIDTH);
cairo_set_source_rgb (cr, color.red, color.green, color.blue);
cairo_rectangle (cr,
SELECT_OUTLINE_WIDTH / 2.0, SELECT_OUTLINE_WIDTH / 2.0,
allocation.width - SELECT_OUTLINE_WIDTH,
allocation.height - SELECT_OUTLINE_WIDTH);
cairo_stroke (cr);
}
return TRUE;
}
static void
meta_select_workspace_get_preferred_width (GtkWidget *widget,
gint *minimum_width,
gint *natural_width)
{
GTK_WIDGET_CLASS (meta_select_workspace_parent_class)->get_preferred_width (widget,
minimum_width,
natural_width);
*minimum_width += SELECT_OUTLINE_WIDTH * 2;
*natural_width += SELECT_OUTLINE_WIDTH * 2;
}
static void
meta_select_workspace_get_preferred_height (GtkWidget *widget,
gint *minimum_height,
gint *natural_height)
{
GTK_WIDGET_CLASS (meta_select_workspace_parent_class)->get_preferred_height (widget,
minimum_height,
natural_height);
*minimum_height += SELECT_OUTLINE_WIDTH * 2;
*natural_height += SELECT_OUTLINE_WIDTH * 2;
}
static void
meta_select_workspace_init (MetaSelectWorkspace *workspace)
{
workspace->priv = meta_select_workspace_get_instance_private (workspace);
}
static void
meta_select_workspace_class_init (MetaSelectWorkspaceClass *class)
{
GtkWidgetClass *widget_class;
widget_class = GTK_WIDGET_CLASS (class);
widget_class->draw = meta_select_workspace_draw;
widget_class->get_preferred_width = meta_select_workspace_get_preferred_width;
widget_class->get_preferred_height = meta_select_workspace_get_preferred_height;
}
GtkWidget *
meta_select_workspace_new (MetaWorkspace *workspace)
{
GtkWidget *widget;
MetaSelectWorkspace *select;
double screen_aspect;
widget = g_object_new (META_TYPE_SELECT_WORKSPACE, NULL);
select = META_SELECT_WORKSPACE (widget);
screen_aspect = (double) workspace->screen->rect.height /
(double) workspace->screen->rect.width;
gtk_widget_set_size_request (widget,
MINI_WORKSPACE_WIDTH + SELECT_OUTLINE_WIDTH * 2,
MINI_WORKSPACE_WIDTH * screen_aspect + SELECT_OUTLINE_WIDTH * 2);
select->priv->workspace = workspace;
return widget;
}
void
meta_select_workspace_select (MetaSelectWorkspace *workspace)
{
workspace->priv->selected = TRUE;
gtk_widget_queue_draw (GTK_WIDGET (workspace));
}
void
meta_select_workspace_unselect (MetaSelectWorkspace *workspace)
{
workspace->priv->selected = FALSE;
gtk_widget_queue_draw (GTK_WIDGET (workspace));
}