Commit 21715d41 authored by Vincent Untz's avatar Vincent Untz Committed by Vincent Untz
Browse files

Improve handling of size hints from applets. This is needed to have the

2007-06-26  Vincent Untz  <vuntz@gnome.org>

	Improve handling of size hints from applets. This is needed to have
	the latest tasklist (libwnck 2.19.5) to correctly work.
	For non-expanded panels, this means we have to "forward" the size
	hints from all applets using it from PanelWidget to PanelToplevel.
	This is a non-trivial change because it might break panel
	sizing and positioning...

	* panel-toplevel.c: (panel_toplevel_update_size_from_hints): new, when
	there are size hints, try to share all the remaining space on the
	screen that is not needed by applets not using size hints between
	applets using size hints. This breaks a bit the separation between
	PanelWidget and PanelToplevel, but I can't think of any other way to
	do this.
	(panel_toplevel_update_size): use
	panel_toplevel_update_size_from_hints(), and make it nicely work for
	drawers
	* panel-widget.[ch]: (panel_widget_size_request): don't take into
	account for the size request applets using size hints. Instead, keep a
	list of those applets, to be used later.
	(panel_widget_count_expanded_applets): kill
	(panel_widget_size_allocate):
	 - for packed panels: the toplevel will have decided which size to use
	   for applets using size hints. We don't need the "compression" part
	   anymore. Of course, we can have an overflow, but we didn't handle
	   this before anyway, so...
	 - for expanded panels: the cell and the minimum cell should be the
	   minimum size in the size hints for applets using size hints: using
	   the requested size is wrong since the requested size generally is
	   "the best size" for the applet, which is not the smaller size the
	   applet can handle. Also fix minor bugs where the minimum cell for
	   applets using size hints is just too big for the panel.
	(panel_widget_finalize): clean new fields
	(panel_widget_init): init new fields
	(panel_widget_set_applet_size_hints): check that the size hints are
	valid before accepting them
	* panel-applet-frame.c:
	(panel_applet_frame_set_size_hints_from_any): simplify a bit

svn path=/trunk/; revision=10480
parent eb177e5b
2007-06-26 Vincent Untz <vuntz@gnome.org>
Improve handling of size hints from applets. This is needed to have
the latest tasklist (libwnck 2.19.5) to correctly work.
For non-expanded panels, this means we have to "forward" the size
hints from all applets using it from PanelWidget to PanelToplevel.
This is a non-trivial change because it might break panel
sizing and positioning...
* panel-toplevel.c: (panel_toplevel_update_size_from_hints): new, when
there are size hints, try to share all the remaining space on the
screen that is not needed by applets not using size hints between
applets using size hints. This breaks a bit the separation between
PanelWidget and PanelToplevel, but I can't think of any other way to
do this.
(panel_toplevel_update_size): use
panel_toplevel_update_size_from_hints(), and make it nicely work for
drawers
* panel-widget.[ch]: (panel_widget_size_request): don't take into
account for the size request applets using size hints. Instead, keep a
list of those applets, to be used later.
(panel_widget_count_expanded_applets): kill
(panel_widget_size_allocate):
- for packed panels: the toplevel will have decided which size to use
for applets using size hints. We don't need the "compression" part
anymore. Of course, we can have an overflow, but we didn't handle
this before anyway, so...
- for expanded panels: the cell and the minimum cell should be the
minimum size in the size hints for applets using size hints: using
the requested size is wrong since the requested size generally is
"the best size" for the applet, which is not the smaller size the
applet can handle. Also fix minor bugs where the minimum cell for
applets using size hints is just too big for the panel.
(panel_widget_finalize): clean new fields
(panel_widget_init): init new fields
(panel_widget_set_applet_size_hints): check that the size hints are
valid before accepting them
* panel-applet-frame.c:
(panel_applet_frame_set_size_hints_from_any): simplify a bit
2007-06-26 Vincent Untz <vuntz@gnome.org>
 
* panel.c: (drop_uri): fix call to panel_util_get_label_for_uri()
......
......@@ -219,12 +219,12 @@ panel_applet_frame_set_size_hints_from_any (PanelAppletFrame *frame,
size_hints = g_new0 (int, seq->_length);
extra_size = 0;
if (frame->priv->has_handle)
if (frame->priv->has_handle) {
extra_size = HANDLE_SIZE + 1;
for (i = 0; i < seq->_length; i++)
size_hints [i] = seq->_buffer [i] + extra_size;
for (i = 0; i < seq->_length; i++)
size_hints [i] = seq->_buffer [i] + extra_size;
}
panel_widget_set_applet_size_hints (frame->priv->panel,
GTK_WIDGET (frame),
......
......@@ -2195,6 +2195,93 @@ calculate_minimum_height (GtkWidget *widget,
return PANGO_PIXELS (ascent + descent) + 2 * (focus_width + focus_pad + thickness);
}
static int
panel_toplevel_update_size_from_hints (PanelToplevel *toplevel,
int requisition_size,
int monitor_size,
int non_panel_widget_size)
{
int nb_size_hints;
AppletSizeHints *applets_hints;
AppletSizeHintsAlloc *using_hint;
int i;
int total_size;
int full_hints;
total_size = non_panel_widget_size + requisition_size;
nb_size_hints = toplevel->priv->panel_widget->nb_applets_size_hints;
if (nb_size_hints <= 0)
return total_size;
applets_hints = toplevel->priv->panel_widget->applets_hints;
using_hint = toplevel->priv->panel_widget->applets_using_hint;
for (i = 0; i < nb_size_hints; i++) {
using_hint[i].index = applets_hints[i].len - 2;
using_hint[i].size = applets_hints[i].hints[applets_hints[i].len - 1];
total_size += using_hint[i].size;
}
if (total_size > monitor_size)
return monitor_size;
full_hints = 0;
while (full_hints != nb_size_hints && total_size < monitor_size) {
int bonus;
int extra_bonus;
bonus = (monitor_size - total_size)
/ (nb_size_hints - full_hints);
extra_bonus = (monitor_size - total_size)
% (nb_size_hints - full_hints);
full_hints = 0;
for (i = 0; i < nb_size_hints; i++) {
int new_size;
int current_bonus;
current_bonus = bonus;
while (using_hint[i].index > 0 && applets_hints[i].hints[using_hint[i].index - 1] < using_hint[i].size + current_bonus) {
new_size = applets_hints[i].hints[using_hint[i].index - 1];
current_bonus = using_hint[i].size
+ current_bonus - new_size;
total_size = total_size - using_hint[i].size
+ new_size;
using_hint[i].index -= 2;
using_hint[i].size = new_size;
}
new_size = MIN (applets_hints[i].hints[using_hint[i].index],
using_hint[i].size + current_bonus);
if (new_size > using_hint[i].size) {
total_size += (new_size - using_hint[i].size);
using_hint[i].size = new_size;
}
if (extra_bonus > 0) {
new_size = MIN (applets_hints[i].hints[using_hint[i].index],
using_hint[i].size + extra_bonus);
if (new_size > using_hint[i].size) {
total_size += (new_size
- using_hint[i].size);
extra_bonus -= (new_size
- using_hint[i].size);
using_hint[i].size = new_size;
}
}
if (using_hint[i].size == applets_hints[i].hints[using_hint[i].index])
full_hints++;
}
}
return total_size;
}
static void
panel_toplevel_update_size (PanelToplevel *toplevel,
GtkRequisition *requisition)
......@@ -2203,6 +2290,7 @@ panel_toplevel_update_size (PanelToplevel *toplevel,
int monitor_width, monitor_height;
int width, height;
int minimum_height;
int non_panel_widget_size;
if (toplevel->priv->animating)
return;
......@@ -2215,29 +2303,70 @@ panel_toplevel_update_size (PanelToplevel *toplevel,
width = requisition->width;
height = requisition->height;
if (!toplevel->priv->expand &&
!toplevel->priv->buttons_enabled && !toplevel->priv->attached)
non_panel_widget_size = 2 * HANDLE_SIZE;
else
non_panel_widget_size = 0;
minimum_height = calculate_minimum_height (GTK_WIDGET (toplevel),
toplevel->priv->orientation);
if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) {
height = MAX (MAX (height, toplevel->priv->size), minimum_height);
if (toplevel->priv->expand)
width = monitor_width;
else if (!toplevel->priv->buttons_enabled &&
!toplevel->priv->attached)
width = MAX (MINIMUM_WIDTH, width + 2 * HANDLE_SIZE);
else
width = MAX (MINIMUM_WIDTH, width);
else {
int max_width;
if (!toplevel->priv->attached)
max_width = monitor_width;
else {
if (panel_toplevel_get_orientation (toplevel->priv->attach_toplevel) == PANEL_ORIENTATION_LEFT)
max_width = monitor_width
- toplevel->priv->geometry.x;
else
max_width = toplevel->priv->geometry.x +
toplevel->priv->geometry.width;
}
width = panel_toplevel_update_size_from_hints (
toplevel,
requisition->width,
max_width,
non_panel_widget_size);
}
width = MAX (MINIMUM_WIDTH, width);
} else {
width = MAX (MAX (width, toplevel->priv->size), minimum_height);
if (toplevel->priv->expand)
height = monitor_height;
else if (!toplevel->priv->buttons_enabled &&
!toplevel->priv->attached)
height = MAX (MINIMUM_WIDTH, height + 2 * HANDLE_SIZE);
else
height = MAX (MINIMUM_WIDTH, height);
else {
int max_height;
if (!toplevel->priv->attached)
max_height = monitor_height;
else {
if (panel_toplevel_get_orientation (toplevel->priv->attach_toplevel) == PANEL_ORIENTATION_TOP)
max_height = monitor_height
- toplevel->priv->geometry.y;
else
max_height = toplevel->priv->geometry.y +
toplevel->priv->geometry.height;
}
height = panel_toplevel_update_size_from_hints (
toplevel,
requisition->height,
max_height,
non_panel_widget_size);
}
height = MAX (MINIMUM_WIDTH, height);
}
if (toplevel->priv->edges & PANEL_EDGE_TOP)
......
......@@ -1191,6 +1191,8 @@ panel_widget_size_request(GtkWidget *widget, GtkRequisition *requisition)
{
PanelWidget *panel;
GList *list;
GList *ad_with_hints;
gboolean dont_fill;
g_return_if_fail(PANEL_IS_WIDGET(widget));
g_return_if_fail(requisition!=NULL);
......@@ -1205,6 +1207,8 @@ panel_widget_size_request(GtkWidget *widget, GtkRequisition *requisition)
requisition->width = panel->sz;
}
ad_with_hints = NULL;
for(list = panel->applet_list; list!=NULL; list = g_list_next(list)) {
AppletData *ad = list->data;
GtkRequisition chreq;
......@@ -1215,7 +1219,8 @@ panel_widget_size_request(GtkWidget *widget, GtkRequisition *requisition)
requisition->height = chreq.height;
if (panel->packed && ad->expand_major && ad->size_hints)
requisition->width += MAX (ad->size_hints [0], chreq.width);
ad_with_hints = g_list_prepend (ad_with_hints,
ad);
else if (panel->packed)
requisition->width += chreq.width;
......@@ -1224,25 +1229,67 @@ panel_widget_size_request(GtkWidget *widget, GtkRequisition *requisition)
requisition->width = chreq.width;
if (panel->packed && ad->expand_major && ad->size_hints)
requisition->height += MAX (ad->size_hints [0], chreq.height);
ad_with_hints = g_list_prepend (ad_with_hints,
ad);
else if (panel->packed)
requisition->height += chreq.height;
}
}
panel->nb_applets_size_hints = 0;
if (panel->applets_hints != NULL)
g_free (panel->applets_hints);
panel->applets_hints = NULL;
if (panel->applets_using_hint != NULL)
g_free (panel->applets_using_hint);
panel->applets_using_hint = NULL;
if(!panel->packed) {
if(panel->orient == GTK_ORIENTATION_HORIZONTAL) {
requisition->width = panel->size;
} else {
requisition->height = panel->size;
}
}
} else {
/* put the list in the correct order: this is important
* since we'll use this order in the size_allocate() */
ad_with_hints = g_list_reverse (ad_with_hints);
panel->nb_applets_size_hints = g_list_length (ad_with_hints);
if (panel->nb_applets_size_hints > 0) {
int i;
panel->applets_hints = g_new0 (AppletSizeHints, panel->nb_applets_size_hints);
i = 0;
for (list = ad_with_hints;
list != NULL;
list = g_list_next (list)) {
AppletData *ad = list->data;
panel->applets_hints[i].hints = ad->size_hints;
panel->applets_hints[i].len = ad->size_hints_len;
i++;
}
panel->applets_using_hint = g_new0 (AppletSizeHintsAlloc, panel->nb_applets_size_hints);
}
}
if (requisition->width < 12)
requisition->width = 12;
if (requisition->height < 12)
requisition->height = 12;
dont_fill = panel->packed && panel->nb_applets_size_hints != 0;
if (panel->orient == GTK_ORIENTATION_HORIZONTAL) {
if (requisition->width < 12 && !dont_fill)
requisition->width = 12;
if (requisition->height < 12)
requisition->height = 12;
} else {
if (requisition->width < 12)
requisition->width = 12;
if (requisition->height < 12 && !dont_fill)
requisition->height = 12;
}
}
static void
......@@ -1276,22 +1323,6 @@ panel_widget_set_background_region (PanelWidget *panel)
widget->allocation.height);
}
static int
panel_widget_count_expanded_applets (PanelWidget *panel)
{
GList *li;
int count = 0;
for (li = panel->applet_list; li != NULL; li = li->next) {
AppletData *ad = li->data;
if (ad->expand_major)
count ++;
}
return count;
}
static void
panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
{
......@@ -1325,20 +1356,9 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
panel_widget_right_stick(panel,old_size);
if (panel->packed) {
int compression = 0;
int applets_to_compress = 0;
if (panel->orient == GTK_ORIENTATION_HORIZONTAL &&
widget->requisition.width > allocation->width) {
compression = widget->requisition.width - allocation->width;
} else if (panel->orient == GTK_ORIENTATION_VERTICAL &&
widget->requisition.height > allocation->height) {
compression = widget->requisition.height - allocation->height;
}
if (compression > 0) {
applets_to_compress = panel_widget_count_expanded_applets (panel);
}
/* we're assuming the order is the same as the one that was
* in size_request() */
int applet_using_hint_index = 0;
i = 0;
for(list = panel->applet_list;
......@@ -1358,15 +1378,9 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
challoc.height = allocation->height;
if (ad->expand_major && ad->size_hints) {
int width = ad->size_hints [0];
if (applets_to_compress > 0) {
width -= (compression / applets_to_compress);
compression -= (compression / applets_to_compress);
applets_to_compress --;
}
challoc.width = CLAMP (MAX (width, chreq.width),
chreq.width,
allocation->width - i);
int width = panel->applets_using_hint[applet_using_hint_index].size;
applet_using_hint_index++;
challoc.width = MIN (width, allocation->width - i);
}
ad->cells = challoc.width;
......@@ -1377,15 +1391,9 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
challoc.width = allocation->width;
if (ad->expand_major && ad->size_hints) {
int height = ad->size_hints [0];
if (applets_to_compress > 0) {
height -= (compression / applets_to_compress);
compression -= (compression / applets_to_compress);
applets_to_compress --;
}
challoc.height = CLAMP (MAX (height, chreq.height),
chreq.height,
allocation->height - i);
int height = panel->applets_using_hint[applet_using_hint_index].size;
applet_using_hint_index++;
challoc.height = MIN (height, allocation->height - i);
}
ad->cells = challoc.height;
......@@ -1396,6 +1404,10 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
gtk_widget_size_allocate(ad->applet,&challoc);
i += ad->cells;
}
/* EEEEK, there might be not enough room and we don't handle
* it: all the applets at the right well be unusable */
} else { /*not packed*/
/* First make sure there's enough room on the left */
......@@ -1408,12 +1420,17 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
gtk_widget_get_child_requisition(ad->applet,&chreq);
if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
ad->cells = chreq.width;
else
ad->cells = chreq.height;
if (!ad->expand_major || !ad->size_hints) {
if(panel->orient == GTK_ORIENTATION_HORIZONTAL)
ad->cells = chreq.width;
else
ad->cells = chreq.height;
ad->min_cells = ad->cells;
ad->min_cells = ad->cells;
} else {
ad->cells = ad->size_hints [ad->size_hints_len - 1];
ad->min_cells = ad->size_hints [ad->size_hints_len - 1];
}
ad->constrained = ad->pos;
......@@ -1432,7 +1449,7 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
int cells;
if (ad->constrained + ad->min_cells > i)
ad->constrained = i - ad->min_cells;
ad->constrained = MAX (i - ad->min_cells, 0);
if (ad->expand_major) {
cells = (i - ad->constrained) - 1;
......@@ -1440,6 +1457,7 @@ panel_widget_size_allocate(GtkWidget *widget, GtkAllocation *allocation)
if (ad->size_hints)
cells = get_size_from_hints (ad, cells);
cells = MAX (cells, ad->min_cells);
cells = MIN (cells, panel->size);
ad->cells = cells;
}
......@@ -1604,6 +1622,14 @@ panel_widget_finalize (GObject *obj)
panel_background_free (&panel->background);
if (panel->applets_hints != NULL)
g_free (panel->applets_hints);
panel->applets_hints = NULL;
if (panel->applets_using_hint != NULL)
g_free (panel->applets_using_hint);
panel->applets_using_hint = NULL;
G_OBJECT_CLASS (panel_widget_parent_class)->finalize (obj);
}
......@@ -1678,6 +1704,10 @@ panel_widget_init (PanelWidget *panel)
panel->drop_widget = widget;
panel->open_dialogs = NULL;
panel->nb_applets_size_hints = 0;
panel->applets_hints = NULL;
panel->applets_using_hint = NULL;
panel_background_init (&panel->background,
(PanelBackgroundChangedNotify) panel_widget_background_changed,
panel);
......@@ -2849,8 +2879,13 @@ panel_widget_set_applet_size_hints (PanelWidget *panel,
g_free (ad->size_hints);
ad->size_hints = size_hints;
ad->size_hints_len = size_hints_len;
if (size_hints_len > 0 && (size_hints_len % 2 == 0)) {
ad->size_hints = size_hints;
ad->size_hints_len = size_hints_len;
} else {
g_free (size_hints);
ad->size_hints = NULL;
}
gtk_widget_queue_resize (GTK_WIDGET (panel));
}
......
......@@ -42,6 +42,19 @@ typedef struct _AppletRecord AppletRecord;
typedef struct _AppletData AppletData;
typedef struct _DNDRecord DNDRecord;
typedef struct _AppletSizeHints AppletSizeHints;
typedef struct _AppletSizeHintsAlloc AppletSizeHintsAlloc;
struct _AppletSizeHints {
int *hints;
int len;
};
struct _AppletSizeHintsAlloc {
int index;
int size;
};
struct _AppletData
{
GtkWidget * applet;
......@@ -97,6 +110,12 @@ struct _PanelWidget
GdkEventKey *key_event;
/* helpers to get a good size in packed panels with applets using
* size hints */
int nb_applets_size_hints;
AppletSizeHints *applets_hints;
AppletSizeHintsAlloc *applets_using_hint;
guint packed : 1;
};
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment