add support for a mini icon in the titlebar (update_icon): re-enable
2001-09-15 Havoc Pennington <hp@pobox.com> * src/window.c: add support for a mini icon in the titlebar (update_icon): re-enable support for _NET_WM_ICON * src/session.c (save_state): add an ferror check when writing session file
This commit is contained in:
parent
2830c9d748
commit
39df21227d
13
ChangeLog
13
ChangeLog
@ -1,3 +1,16 @@
|
|||||||
|
2001-09-15 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
|
* src/window.c: add support for a mini icon in the titlebar
|
||||||
|
(update_icon): re-enable support for _NET_WM_ICON
|
||||||
|
|
||||||
|
* src/session.c (save_state): add an ferror check when writing
|
||||||
|
session file
|
||||||
|
|
||||||
|
2001-09-11 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
|
* src/main.c (usage): exit with error code on usage() (kind of
|
||||||
|
wrong for --help, but oh well).
|
||||||
|
|
||||||
2001-09-11 Havoc Pennington <hp@pobox.com>
|
2001-09-11 Havoc Pennington <hp@pobox.com>
|
||||||
|
|
||||||
* src/window.c: fix up handling of text properties, so we
|
* src/window.c: fix up handling of text properties, so we
|
||||||
|
10
configure.in
10
configure.in
@ -62,8 +62,13 @@ if test "$found_sm" = "true"; then
|
|||||||
AC_DEFINE(HAVE_SM)
|
AC_DEFINE(HAVE_SM)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Check for shaped window extension
|
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "true")
|
||||||
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
|
||||||
|
MSM_CFLAGS=$METACITY_CFLAGS
|
||||||
|
MSM_LIBS=$METACITY_LIBS
|
||||||
|
|
||||||
|
AC_SUBST(MSM_CFLAGS)
|
||||||
|
AC_SUBST(MSM_LIBS)
|
||||||
|
|
||||||
HOST_ALIAS=$host_alias
|
HOST_ALIAS=$host_alias
|
||||||
AC_SUBST(HOST_ALIAS)
|
AC_SUBST(HOST_ALIAS)
|
||||||
@ -72,6 +77,7 @@ AC_OUTPUT([
|
|||||||
Makefile
|
Makefile
|
||||||
src/Makefile
|
src/Makefile
|
||||||
src/wm-tester/Makefile
|
src/wm-tester/Makefile
|
||||||
|
src/msm/Makefile
|
||||||
])
|
])
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
|
|
||||||
SUBDIRS=wm-tester
|
if HAVE_SM
|
||||||
|
SM_SUBDIRS=msm
|
||||||
|
else
|
||||||
|
SM_SUBDIRS=
|
||||||
|
endif
|
||||||
|
|
||||||
|
SUBDIRS=wm-tester $(SM_SUBDIRS)
|
||||||
|
|
||||||
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
INCLUDES=@METACITY_CFLAGS@ -DMETACITY_LIBEXECDIR=\"$(libexecdir)\" -DHOST_ALIAS=\"@HOST_ALIAS@\"
|
||||||
|
|
||||||
|
16
src/core.c
16
src/core.c
@ -60,6 +60,22 @@ meta_core_get_frame_flags (Display *xdisplay,
|
|||||||
return meta_frame_get_flags (window->frame);
|
return meta_frame_get_flags (window->frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
meta_core_get_mini_icon (Display *xdisplay,
|
||||||
|
Window frame_xwindow)
|
||||||
|
{
|
||||||
|
MetaDisplay *display;
|
||||||
|
MetaWindow *window;
|
||||||
|
|
||||||
|
display = meta_display_for_x_display (xdisplay);
|
||||||
|
window = meta_display_lookup_x_window (display, frame_xwindow);
|
||||||
|
|
||||||
|
if (window == NULL || window->frame == NULL)
|
||||||
|
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
|
||||||
|
|
||||||
|
return window->mini_icon;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
meta_core_queue_frame_resize (Display *xdisplay,
|
meta_core_queue_frame_resize (Display *xdisplay,
|
||||||
Window frame_xwindow)
|
Window frame_xwindow)
|
||||||
|
@ -36,6 +36,9 @@ void meta_core_get_frame_size (Display *xdisplay,
|
|||||||
MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay,
|
MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay,
|
||||||
Window frame_xwindow);
|
Window frame_xwindow);
|
||||||
|
|
||||||
|
GdkPixbuf* meta_core_get_mini_icon (Display *xdisplay,
|
||||||
|
Window frame_xwindow);
|
||||||
|
|
||||||
void meta_core_queue_frame_resize (Display *xdisplay,
|
void meta_core_queue_frame_resize (Display *xdisplay,
|
||||||
Window frame_xwindow);
|
Window frame_xwindow);
|
||||||
|
|
||||||
|
71
src/frames.c
71
src/frames.c
@ -1740,11 +1740,78 @@ meta_frames_expose_event (GtkWidget *widget,
|
|||||||
|
|
||||||
if (frame->layout)
|
if (frame->layout)
|
||||||
{
|
{
|
||||||
|
PangoRectangle layout_rect;
|
||||||
|
int x, y, icon_x, icon_y;
|
||||||
|
GdkPixbuf *icon;
|
||||||
|
int icon_w, icon_h;
|
||||||
|
int area_w, area_h;
|
||||||
|
|
||||||
|
#define ICON_TEXT_SPACING 2
|
||||||
|
|
||||||
|
icon = meta_core_get_mini_icon (gdk_display,
|
||||||
|
frame->xwindow);
|
||||||
|
|
||||||
|
icon_w = gdk_pixbuf_get_width (icon);
|
||||||
|
icon_h = gdk_pixbuf_get_height (icon);
|
||||||
|
|
||||||
|
pango_layout_get_pixel_extents (frame->layout,
|
||||||
|
NULL,
|
||||||
|
&layout_rect);
|
||||||
|
|
||||||
|
/* corner of whole title area */
|
||||||
|
x = fgeom.title_rect.x + frames->props->text_border.left;
|
||||||
|
y = fgeom.title_rect.y + frames->props->text_border.top;
|
||||||
|
|
||||||
|
area_w = fgeom.title_rect.width -
|
||||||
|
frames->props->text_border.left -
|
||||||
|
frames->props->text_border.right;
|
||||||
|
|
||||||
|
area_h = fgeom.title_rect.height -
|
||||||
|
frames->props->text_border.top -
|
||||||
|
frames->props->text_border.bottom;
|
||||||
|
|
||||||
|
/* center icon vertically */
|
||||||
|
icon_y = y + MAX ((area_h - icon_h) / 2, 0);
|
||||||
|
/* center text vertically */
|
||||||
|
y = y + MAX ((area_h - layout_rect.height) / 2, 0);
|
||||||
|
|
||||||
|
/* Center icon + text combo */
|
||||||
|
icon_x = x + MAX ((area_w - layout_rect.width - icon_w - ICON_TEXT_SPACING) / 2, 0);
|
||||||
|
x = icon_x + icon_w + ICON_TEXT_SPACING;
|
||||||
|
|
||||||
gdk_gc_set_clip_rectangle (layout_gc, &clip);
|
gdk_gc_set_clip_rectangle (layout_gc, &clip);
|
||||||
|
|
||||||
|
{
|
||||||
|
/* grumble, render_to_drawable_alpha does not accept a clip
|
||||||
|
* mask, so we have to go through some BS
|
||||||
|
*/
|
||||||
|
GdkRectangle pixbuf_rect;
|
||||||
|
GdkRectangle draw_rect;
|
||||||
|
|
||||||
|
pixbuf_rect.x = icon_x;
|
||||||
|
pixbuf_rect.y = icon_y;
|
||||||
|
pixbuf_rect.width = icon_w;
|
||||||
|
pixbuf_rect.height = icon_h;
|
||||||
|
|
||||||
|
if (gdk_rectangle_intersect (&clip, &pixbuf_rect, &draw_rect))
|
||||||
|
{
|
||||||
|
gdk_pixbuf_render_to_drawable_alpha (icon,
|
||||||
|
frame->window,
|
||||||
|
draw_rect.x - pixbuf_rect.x,
|
||||||
|
draw_rect.y - pixbuf_rect.y,
|
||||||
|
draw_rect.x, draw_rect.y,
|
||||||
|
draw_rect.width,
|
||||||
|
draw_rect.height,
|
||||||
|
GDK_PIXBUF_ALPHA_FULL,
|
||||||
|
128,
|
||||||
|
GDK_RGB_DITHER_NORMAL,
|
||||||
|
0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
gdk_draw_layout (frame->window,
|
gdk_draw_layout (frame->window,
|
||||||
layout_gc,
|
layout_gc,
|
||||||
fgeom.title_rect.x + frames->props->text_border.left,
|
x, y,
|
||||||
fgeom.title_rect.y + frames->props->text_border.top,
|
|
||||||
frame->layout);
|
frame->layout);
|
||||||
gdk_gc_set_clip_rectangle (layout_gc, NULL);
|
gdk_gc_set_clip_rectangle (layout_gc, NULL);
|
||||||
}
|
}
|
||||||
|
@ -42,7 +42,7 @@ static void
|
|||||||
usage (void)
|
usage (void)
|
||||||
{
|
{
|
||||||
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n");
|
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n");
|
||||||
exit (0);
|
exit (1);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
|
@ -288,25 +288,9 @@ msm_client_set_property_taking_ownership (MsmClient *client,
|
|||||||
SmProp *prop)
|
SmProp *prop)
|
||||||
{
|
{
|
||||||
/* we own prop which should be freed with SmFreeProperty() */
|
/* we own prop which should be freed with SmFreeProperty() */
|
||||||
GList *list;
|
|
||||||
|
|
||||||
if (prop->name == NULL)
|
/* pass our ownership into the proplist */
|
||||||
{
|
client->properties = proplist_replace (client->properties, prop);
|
||||||
SmFreeProperty (prop);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
list = proplist_find_link_by_name (client->properties, prop->name);
|
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
SmFreeProperty (list->data);
|
|
||||||
list->data = prop;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
client->properties = g_list_prepend (client->properties,
|
|
||||||
prop);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* update pieces of the client struct */
|
/* update pieces of the client struct */
|
||||||
if (strcmp (prop->name, "SmRestartStyleHint") == 0)
|
if (strcmp (prop->name, "SmRestartStyleHint") == 0)
|
||||||
@ -323,15 +307,7 @@ void
|
|||||||
msm_client_unset_property (MsmClient *client,
|
msm_client_unset_property (MsmClient *client,
|
||||||
const char *name)
|
const char *name)
|
||||||
{
|
{
|
||||||
GList *list;
|
client->properties = proplist_delete (client->properties, name);
|
||||||
|
|
||||||
list = proplist_find_link_by_name (client->properties, name);
|
|
||||||
if (list)
|
|
||||||
{
|
|
||||||
SmFreeProperty (list->data);
|
|
||||||
client->properties = g_list_delete_link (client->properties,
|
|
||||||
list);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Return to default values */
|
/* Return to default values */
|
||||||
if (strcmp (name, "SmRestartStyleHint") == 0)
|
if (strcmp (name, "SmRestartStyleHint") == 0)
|
||||||
|
359
src/msm/gtkdisclosurebox.c
Normal file
359
src/msm/gtkdisclosurebox.c
Normal file
@ -0,0 +1,359 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
* this file Copyright (C) 2001 Havoc Pennington
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* FIXME implementation contains a bunch of cut-and-paste from GtkFrame
|
||||||
|
* that would be easy to avoid by adding an "int space_before_label_widget"
|
||||||
|
* in GtkFrame that was overridden by subclasses.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* FIXME the whole GtkFrame derivation idea is fucked since we can't get
|
||||||
|
* the click event on the arrow.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define ARROW_SIZE 12
|
||||||
|
#define ARROW_PAD 2
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PROP_0,
|
||||||
|
PROP_DISCLOSED,
|
||||||
|
PROP_LAST
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gtk_disclosure_box_class_init (GtkDisclosureBoxClass *klass);
|
||||||
|
static void gtk_disclosure_box_init (GtkDisclosureBox *box);
|
||||||
|
static void gtk_disclosure_box_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
static void gtk_disclosure_box_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec);
|
||||||
|
|
||||||
|
static void gtk_disclosure_box_paint (GtkWidget *widget,
|
||||||
|
GdkRectangle *area);
|
||||||
|
static gint gtk_disclosure_box_expose (GtkWidget *widget,
|
||||||
|
GdkEventExpose *event);
|
||||||
|
static void gtk_disclosure_box_size_request (GtkWidget *widget,
|
||||||
|
GtkRequisition *requisition);
|
||||||
|
static void gtk_disclosure_box_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation);
|
||||||
|
|
||||||
|
static void gtk_frame_compute_child_allocation (GtkFrame *frame,
|
||||||
|
GtkAllocation *child_allocation);
|
||||||
|
|
||||||
|
GType
|
||||||
|
gtk_disclosure_box_get_type (void)
|
||||||
|
{
|
||||||
|
static GType disclosure_box_type = 0;
|
||||||
|
|
||||||
|
if (!disclosure_box_type)
|
||||||
|
{
|
||||||
|
static const GtkTypeInfo disclosure_box_info =
|
||||||
|
{
|
||||||
|
"GtkDisclosureBox",
|
||||||
|
sizeof (GtkDisclosureBox),
|
||||||
|
sizeof (GtkDisclosureBoxClass),
|
||||||
|
(GtkClassInitFunc) gtk_disclosure_box_class_init,
|
||||||
|
(GtkObjectInitFunc) gtk_disclosure_box_init,
|
||||||
|
/* reserved_1 */ NULL,
|
||||||
|
/* reserved_2 */ NULL,
|
||||||
|
(GtkClassInitFunc) NULL,
|
||||||
|
};
|
||||||
|
|
||||||
|
disclosure_box_type = gtk_type_unique (gtk_box_get_type (), &disclosure_box_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
return disclosure_box_type;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_class_init (GtkDisclosureBoxClass *class)
|
||||||
|
{
|
||||||
|
GtkWidgetClass *widget_class;
|
||||||
|
GObjectClass *gobject_class;
|
||||||
|
GtkContainerClass *container_class;
|
||||||
|
GtkFrameClass *frame_class;
|
||||||
|
|
||||||
|
gobject_class = G_OBJECT_CLASS (class);
|
||||||
|
widget_class = GTK_WIDGET_CLASS (class);
|
||||||
|
container_class = GTK_CONTAINER_CLASS (class);
|
||||||
|
frame_class = GTK_FRAME_CLASS (class);
|
||||||
|
|
||||||
|
gobject_class->set_property = gtk_disclosure_box_set_property;
|
||||||
|
gobject_class->get_property = gtk_disclosure_box_get_property;
|
||||||
|
|
||||||
|
widget_class->size_request = gtk_disclosure_box_size_request;
|
||||||
|
widget_class->size_allocate = gtk_disclosure_box_size_allocate;
|
||||||
|
widget_class->expose_event = gtk_disclosure_box_expose;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_init (GtkDisclosureBox *disclosure_box)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
GtkWidget*
|
||||||
|
gtk_disclosure_box_new (const char *label)
|
||||||
|
{
|
||||||
|
return g_object_new (GTK_TYPE_DISCLOSURE_BOX, "label", label, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_set_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
const GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkDisclosureBox *box;
|
||||||
|
|
||||||
|
box = GTK_DISCLOSURE_BOX (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DISCLOSED:
|
||||||
|
gtk_disclosure_box_set_disclosed (box,
|
||||||
|
g_value_get_boolean (value));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_get_property (GObject *object,
|
||||||
|
guint prop_id,
|
||||||
|
GValue *value,
|
||||||
|
GParamSpec *pspec)
|
||||||
|
{
|
||||||
|
GtkDisclosureBox *box;
|
||||||
|
|
||||||
|
box = GTK_DISCLOSURE_BOX (object);
|
||||||
|
|
||||||
|
switch (prop_id)
|
||||||
|
{
|
||||||
|
case PROP_DISCLOSED:
|
||||||
|
g_value_set_boolean (value, box->disclosed);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
gtk_disclosure_box_set_disclosed (GtkDisclosureBox *box,
|
||||||
|
gboolean disclosed)
|
||||||
|
{
|
||||||
|
g_return_if_fail (GTK_IS_DISCLOSURE_BOX (box));
|
||||||
|
|
||||||
|
disclosed = disclosed != FALSE;
|
||||||
|
|
||||||
|
if (disclosed != box->disclosed)
|
||||||
|
{
|
||||||
|
box->disclosed = disclosed;
|
||||||
|
gtk_widget_queue_resize (GTK_WIDGET (box));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gboolean
|
||||||
|
gtk_disclosure_box_get_disclosed (GtkDisclosureBox *box)
|
||||||
|
{
|
||||||
|
g_return_val_if_fail (GTK_IS_DISCLOSURE_BOX (box), FALSE);
|
||||||
|
|
||||||
|
return box->disclosed;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_paint (GtkWidget *widget,
|
||||||
|
GdkRectangle *area)
|
||||||
|
{
|
||||||
|
GtkFrame *frame;
|
||||||
|
gint x, y, width, height;
|
||||||
|
|
||||||
|
if (GTK_WIDGET_DRAWABLE (widget))
|
||||||
|
{
|
||||||
|
frame = GTK_FRAME (widget);
|
||||||
|
|
||||||
|
x = frame->child_allocation.x - widget->style->xthickness;
|
||||||
|
y = frame->child_allocation.y - widget->style->ythickness;
|
||||||
|
width = frame->child_allocation.width + 2 * widget->style->xthickness;
|
||||||
|
height = frame->child_allocation.height + 2 * widget->style->ythickness;
|
||||||
|
|
||||||
|
if (frame->label_widget)
|
||||||
|
{
|
||||||
|
GtkRequisition child_requisition;
|
||||||
|
gfloat xalign;
|
||||||
|
gint height_extra;
|
||||||
|
gint x2;
|
||||||
|
|
||||||
|
gtk_widget_get_child_requisition (frame->label_widget, &child_requisition);
|
||||||
|
|
||||||
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||||
|
xalign = frame->label_xalign;
|
||||||
|
else
|
||||||
|
xalign = 1 - frame->label_xalign;
|
||||||
|
|
||||||
|
height_extra = MAX (0, child_requisition.height - widget->style->xthickness);
|
||||||
|
y -= height_extra * (1 - frame->label_yalign);
|
||||||
|
height += height_extra * (1 - frame->label_yalign);
|
||||||
|
|
||||||
|
x2 = widget->style->xthickness + (frame->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_SIDE_PAD;
|
||||||
|
|
||||||
|
|
||||||
|
gtk_paint_shadow_gap (widget->style, widget->window,
|
||||||
|
GTK_STATE_NORMAL, frame->shadow_type,
|
||||||
|
area, widget, "frame",
|
||||||
|
x, y, width, height,
|
||||||
|
GTK_POS_TOP,
|
||||||
|
x2 + ARROW_SIZE + ARROW_PAD * 2, child_requisition.width + 2 * LABEL_PAD);
|
||||||
|
|
||||||
|
gtk_paint_arrow (widget->style, widget->window,
|
||||||
|
widget->state, GTK_SHADOW_OUT,
|
||||||
|
area, widget, "arrow",
|
||||||
|
GTK_DISCLOSURE_BOX (widget)->disclosed ?
|
||||||
|
GTK_ARROW_RIGHT : GTK_ARROW_DOWN,
|
||||||
|
TRUE,
|
||||||
|
x2 + ARROW_PAD, y, ARROW_SIZE, ARROW_SIZE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
gtk_paint_shadow (widget->style, widget->window,
|
||||||
|
GTK_STATE_NORMAL, frame->shadow_type,
|
||||||
|
area, widget, "frame",
|
||||||
|
x, y, width, height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gtk_disclosure_box_expose (GtkWidget *widget,
|
||||||
|
GdkEventExpose *event)
|
||||||
|
{
|
||||||
|
if (GTK_WIDGET_DRAWABLE (widget))
|
||||||
|
{
|
||||||
|
gtk_disclosure_box_paint (widget, &event->area);
|
||||||
|
|
||||||
|
(* GTK_WIDGET_CLASS (parent_class)->expose_event) (widget, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_size_request (GtkWidget *widget,
|
||||||
|
GtkRequisition *requisition)
|
||||||
|
{
|
||||||
|
GtkFrame *frame = GTK_FRAME (widget);
|
||||||
|
GtkBin *bin = GTK_BIN (widget);
|
||||||
|
GtkRequisition child_requisition;
|
||||||
|
|
||||||
|
if (frame->label_widget && GTK_WIDGET_VISIBLE (frame->label_widget))
|
||||||
|
{
|
||||||
|
gtk_widget_size_request (frame->label_widget, &child_requisition);
|
||||||
|
|
||||||
|
requisition->width = child_requisition.width + 2 * LABEL_PAD + 2 * LABEL_SIDE_PAD + ARROW_SIZE + ARROW_PAD * 2;
|
||||||
|
requisition->height =
|
||||||
|
MAX (0, child_requisition.height - GTK_WIDGET (widget)->style->xthickness);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
requisition->width = 0;
|
||||||
|
requisition->height = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
|
||||||
|
{
|
||||||
|
gtk_widget_size_request (bin->child, &child_requisition);
|
||||||
|
|
||||||
|
requisition->width = MAX (requisition->width, child_requisition.width);
|
||||||
|
requisition->height += child_requisition.height;
|
||||||
|
}
|
||||||
|
|
||||||
|
requisition->width += (GTK_CONTAINER (widget)->border_width +
|
||||||
|
GTK_WIDGET (widget)->style->xthickness) * 2;
|
||||||
|
requisition->height += (GTK_CONTAINER (widget)->border_width +
|
||||||
|
GTK_WIDGET (widget)->style->ythickness) * 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gtk_disclosure_box_size_allocate (GtkWidget *widget,
|
||||||
|
GtkAllocation *allocation)
|
||||||
|
{
|
||||||
|
GtkFrame *frame = GTK_FRAME (widget);
|
||||||
|
GtkBin *bin = GTK_BIN (widget);
|
||||||
|
GtkAllocation new_allocation;
|
||||||
|
|
||||||
|
widget->allocation = *allocation;
|
||||||
|
|
||||||
|
gtk_frame_compute_child_allocation (frame, &new_allocation);
|
||||||
|
|
||||||
|
/* If the child allocation changed, that means that the frame is drawn
|
||||||
|
* in a new place, so we must redraw the entire widget.
|
||||||
|
*/
|
||||||
|
if (GTK_WIDGET_MAPPED (widget) &&
|
||||||
|
(new_allocation.x != frame->child_allocation.x ||
|
||||||
|
new_allocation.y != frame->child_allocation.y ||
|
||||||
|
new_allocation.width != frame->child_allocation.width ||
|
||||||
|
new_allocation.height != frame->child_allocation.height))
|
||||||
|
gtk_widget_queue_clear (widget);
|
||||||
|
|
||||||
|
if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
|
||||||
|
gtk_widget_size_allocate (bin->child, &new_allocation);
|
||||||
|
|
||||||
|
frame->child_allocation = new_allocation;
|
||||||
|
|
||||||
|
if (frame->label_widget && GTK_WIDGET_VISIBLE (frame->label_widget))
|
||||||
|
{
|
||||||
|
GtkRequisition child_requisition;
|
||||||
|
GtkAllocation child_allocation;
|
||||||
|
gfloat xalign;
|
||||||
|
|
||||||
|
gtk_widget_get_child_requisition (frame->label_widget, &child_requisition);
|
||||||
|
|
||||||
|
if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
|
||||||
|
xalign = frame->label_xalign;
|
||||||
|
else
|
||||||
|
xalign = 1 - frame->label_xalign;
|
||||||
|
|
||||||
|
child_allocation.x = frame->child_allocation.x + LABEL_SIDE_PAD +
|
||||||
|
(frame->child_allocation.width - child_requisition.width - 2 * LABEL_PAD - 2 * LABEL_SIDE_PAD) * xalign + LABEL_PAD + ARROW_SIZE + ARROW_PAD * 2;
|
||||||
|
child_allocation.width = child_requisition.width;
|
||||||
|
|
||||||
|
child_allocation.y = frame->child_allocation.y - child_requisition.height;
|
||||||
|
child_allocation.height = child_requisition.height;
|
||||||
|
|
||||||
|
gtk_widget_size_allocate (frame->label_widget, &child_allocation);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
76
src/msm/gtkdisclosurebox.h
Normal file
76
src/msm/gtkdisclosurebox.h
Normal file
@ -0,0 +1,76 @@
|
|||||||
|
/* GTK - The GIMP Toolkit
|
||||||
|
* Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
|
||||||
|
* this file Copyright (C) 2001 Havoc Pennington
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the
|
||||||
|
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
|
||||||
|
* Boston, MA 02111-1307, USA.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Modified by the GTK+ Team and others 1997-2000. See the AUTHORS
|
||||||
|
* file for a list of people on the GTK+ Team. See the ChangeLog
|
||||||
|
* files for a list of changes. These files are distributed with
|
||||||
|
* GTK+ at ftp://ftp.gtk.org/pub/gtk/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GTK_DISCLOSURE_BOX_H__
|
||||||
|
#define __GTK_DISCLOSURE_BOX_H__
|
||||||
|
|
||||||
|
|
||||||
|
#include <gdk/gdk.h>
|
||||||
|
#include <gtk/gtkframe.h>
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#define GTK_TYPE_DISCLOSURE_BOX (gtk_disclosure_box_get_type ())
|
||||||
|
#define GTK_DISCLOSURE_BOX(obj) (GTK_CHECK_CAST ((obj), GTK_TYPE_DISCLOSURE_BOX, GtkDisclosureBox))
|
||||||
|
#define GTK_DISCLOSURE_BOX_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_DISCLOSURE_BOX, GtkDisclosureBoxClass))
|
||||||
|
#define GTK_IS_DISCLOSURE_BOX(obj) (GTK_CHECK_TYPE ((obj), GTK_TYPE_DISCLOSURE_BOX))
|
||||||
|
#define GTK_IS_DISCLOSURE_BOX_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_DISCLOSURE_BOX))
|
||||||
|
#define GTK_DISCLOSURE_BOX_GET_CLASS(obj) (GTK_CHECK_GET_CLASS ((obj), GTK_TYPE_DISCLOSURE_BOX, GtkDisclosureBoxClass))
|
||||||
|
|
||||||
|
typedef struct _GtkDisclosureBox GtkDisclosureBox;
|
||||||
|
typedef struct _GtkDisclosureBoxClass GtkDisclosureBoxClass;
|
||||||
|
|
||||||
|
struct _GtkDisclosureBox
|
||||||
|
{
|
||||||
|
GtkFrame parent_instance;
|
||||||
|
|
||||||
|
guint disclosed : 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct _GtkDisclosureBoxClass
|
||||||
|
{
|
||||||
|
GtkFrameClass parent_class;
|
||||||
|
};
|
||||||
|
|
||||||
|
GType gtk_disclosure_box_get_type (void) G_GNUC_CONST;
|
||||||
|
|
||||||
|
GtkWidget* gtk_disclosure_box_new (const char *label);
|
||||||
|
|
||||||
|
void gtk_disclosure_box_set_disclosed (GtkDisclosureBox *box,
|
||||||
|
gboolean disclosed);
|
||||||
|
gboolean gtk_disclosure_box_get_disclosed (GtkDisclosureBox *box);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif /* __cplusplus */
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* __GTK_FRAME_H__ */
|
141
src/msm/props.c
141
src/msm/props.c
@ -82,6 +82,80 @@ proplist_find_string (GList *list, const char *name,
|
|||||||
return smprop_get_string (prop, result);
|
return smprop_get_string (prop, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GList*
|
||||||
|
proplist_replace (GList *list,
|
||||||
|
SmProp *new_prop)
|
||||||
|
{
|
||||||
|
GList *link;
|
||||||
|
|
||||||
|
link = proplist_find_link_by_name (list, new_prop->name);
|
||||||
|
if (link)
|
||||||
|
{
|
||||||
|
SmFreeProperty (link->data);
|
||||||
|
link->data = new_prop;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
list = g_list_prepend (list, new_prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList*
|
||||||
|
proplist_delete (GList *list,
|
||||||
|
const char *name)
|
||||||
|
{
|
||||||
|
GList *link;
|
||||||
|
|
||||||
|
link = proplist_find_link_by_name (list, name);
|
||||||
|
if (link)
|
||||||
|
{
|
||||||
|
SmFreeProperty (link->data);
|
||||||
|
list = g_list_delete_link (list, link);
|
||||||
|
}
|
||||||
|
|
||||||
|
return list;
|
||||||
|
}
|
||||||
|
|
||||||
|
GList*
|
||||||
|
proplist_replace_card8 (GList *list,
|
||||||
|
const char *name,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
SmProp *prop;
|
||||||
|
|
||||||
|
prop = smprop_new_card8 (name, value);
|
||||||
|
|
||||||
|
return proplist_replace (list, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
GList*
|
||||||
|
proplist_replace_string (GList *list,
|
||||||
|
const char *name,
|
||||||
|
const char *str,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
SmProp *prop;
|
||||||
|
|
||||||
|
prop = smprop_new_string (name, str, len);
|
||||||
|
|
||||||
|
return proplist_replace (list, prop);
|
||||||
|
}
|
||||||
|
|
||||||
|
GList*
|
||||||
|
proplist_replace_vector (GList *list,
|
||||||
|
const char *name,
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
SmProp *prop;
|
||||||
|
|
||||||
|
prop = smprop_new_vector (name, argc, argv);
|
||||||
|
|
||||||
|
return proplist_replace (list, prop);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
proplist_find_vector (GList *list, const char *name,
|
proplist_find_vector (GList *list, const char *name,
|
||||||
int *argcp, char ***argvp)
|
int *argcp, char ***argvp)
|
||||||
@ -206,5 +280,72 @@ smprop_copy (SmProp *prop)
|
|||||||
return copy;
|
return copy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SmProp*
|
||||||
|
smprop_new_vector (const char *name,
|
||||||
|
int argc,
|
||||||
|
char **argv)
|
||||||
|
{
|
||||||
|
SmProp *prop;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
prop = msm_non_glib_malloc (sizeof (SmProp));
|
||||||
|
prop->name = msm_non_glib_strdup (name);
|
||||||
|
prop->type = msm_non_glib_strdup (SmLISTofARRAY8);
|
||||||
|
|
||||||
|
prop->num_vals = argc;
|
||||||
|
prop->vals = msm_non_glib_malloc (sizeof (SmPropValue) * prop->num_vals);
|
||||||
|
i = 0;
|
||||||
|
while (i < argc)
|
||||||
|
{
|
||||||
|
prop->vals[i].length = strlen (argv[i]);
|
||||||
|
prop->vals[i].value = msm_non_glib_strdup (argv[i]);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmProp*
|
||||||
|
smprop_new_string (const char *name,
|
||||||
|
const char *str,
|
||||||
|
int len)
|
||||||
|
{
|
||||||
|
SmProp *prop;
|
||||||
|
|
||||||
|
if (len < 0)
|
||||||
|
len = strlen (str);
|
||||||
|
|
||||||
|
prop = msm_non_glib_malloc (sizeof (SmProp));
|
||||||
|
prop->name = msm_non_glib_strdup (name);
|
||||||
|
prop->type = msm_non_glib_strdup (SmARRAY8);
|
||||||
|
|
||||||
|
prop->num_vals = 1;
|
||||||
|
prop->vals = msm_non_glib_malloc (sizeof (SmPropValue) * prop->num_vals);
|
||||||
|
|
||||||
|
prop->vals[0].length = len;
|
||||||
|
prop->vals[0].value = msm_non_glib_malloc (len);
|
||||||
|
memcpy (prop->vals[0].value, str, len);
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
|
||||||
|
SmProp*
|
||||||
|
smprop_new_card8 (const char *name,
|
||||||
|
int value)
|
||||||
|
{
|
||||||
|
SmProp *prop;
|
||||||
|
|
||||||
|
prop = msm_non_glib_malloc (sizeof (SmProp));
|
||||||
|
prop->name = msm_non_glib_strdup (name);
|
||||||
|
prop->type = msm_non_glib_strdup (SmARRAY8);
|
||||||
|
|
||||||
|
prop->num_vals = 1;
|
||||||
|
prop->vals = msm_non_glib_malloc (sizeof (SmPropValue) * prop->num_vals);
|
||||||
|
|
||||||
|
prop->vals[0].length = 1;
|
||||||
|
prop->vals[0].value = msm_non_glib_malloc (1);
|
||||||
|
(* (char*) prop->vals[0].value) = (char) value;
|
||||||
|
|
||||||
|
return prop;
|
||||||
|
}
|
||||||
|
@ -41,6 +41,24 @@ gboolean proplist_find_vector (GList *list,
|
|||||||
int *argcp,
|
int *argcp,
|
||||||
char ***argvp);
|
char ***argvp);
|
||||||
|
|
||||||
|
GList* proplist_replace (GList *list,
|
||||||
|
SmProp *new_prop);
|
||||||
|
|
||||||
|
GList* proplist_delete (GList *list,
|
||||||
|
const char *name);
|
||||||
|
|
||||||
|
GList* proplist_replace_card8 (GList *list,
|
||||||
|
const char *name,
|
||||||
|
int value);
|
||||||
|
GList* proplist_replace_string (GList *list,
|
||||||
|
const char *name,
|
||||||
|
const char *str,
|
||||||
|
int len);
|
||||||
|
GList* proplist_replace_vector (GList *list,
|
||||||
|
const char *name,
|
||||||
|
int argc,
|
||||||
|
char **argv);
|
||||||
|
|
||||||
gboolean smprop_get_card8 (SmProp *prop,
|
gboolean smprop_get_card8 (SmProp *prop,
|
||||||
int *result);
|
int *result);
|
||||||
gboolean smprop_get_string (SmProp *prop,
|
gboolean smprop_get_string (SmProp *prop,
|
||||||
@ -49,6 +67,16 @@ gboolean smprop_get_vector (SmProp *prop,
|
|||||||
int *argcp,
|
int *argcp,
|
||||||
char ***argvp);
|
char ***argvp);
|
||||||
|
|
||||||
|
SmProp* smprop_new_card8 (const char *name,
|
||||||
|
int value);
|
||||||
|
SmProp* smprop_new_string (const char *name,
|
||||||
|
const char *str,
|
||||||
|
int len);
|
||||||
|
SmProp* smprop_new_vector (const char *name,
|
||||||
|
int argc,
|
||||||
|
char **argv);
|
||||||
|
|
||||||
|
|
||||||
SmProp* smprop_copy (SmProp *prop);
|
SmProp* smprop_copy (SmProp *prop);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include <gtk/gtk.h>
|
#include <gtk/gtk.h>
|
||||||
|
|
||||||
@ -38,7 +39,7 @@ typedef struct _MsmSavedClient MsmSavedClient;
|
|||||||
struct _MsmSavedClient
|
struct _MsmSavedClient
|
||||||
{
|
{
|
||||||
char *id;
|
char *id;
|
||||||
|
GList *properties;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _MsmSession
|
struct _MsmSession
|
||||||
@ -71,6 +72,9 @@ static MsmSession* recover_failed_session (MsmSession *session,
|
|||||||
static gboolean parse_session_file (MsmSession *session,
|
static gboolean parse_session_file (MsmSession *session,
|
||||||
GError **error);
|
GError **error);
|
||||||
|
|
||||||
|
static char* decode_text_from_utf8 (const char *text);
|
||||||
|
static char* encode_text_as_utf8 (const char *text);
|
||||||
|
|
||||||
void
|
void
|
||||||
msm_session_clear (MsmSession *session)
|
msm_session_clear (MsmSession *session)
|
||||||
{
|
{
|
||||||
@ -106,8 +110,10 @@ msm_session_client_id_known (MsmSession *session,
|
|||||||
void
|
void
|
||||||
msm_session_launch (MsmSession *session)
|
msm_session_launch (MsmSession *session)
|
||||||
{
|
{
|
||||||
|
system ("xclock &");
|
||||||
|
system ("xclock &");
|
||||||
|
system ("xclock &");
|
||||||
|
system ("xterm &");
|
||||||
}
|
}
|
||||||
|
|
||||||
MsmSavedClient*
|
MsmSavedClient*
|
||||||
@ -118,7 +124,8 @@ saved_new (void)
|
|||||||
saved = g_new (MsmSavedClient, 1);
|
saved = g_new (MsmSavedClient, 1);
|
||||||
|
|
||||||
saved->id = NULL;
|
saved->id = NULL;
|
||||||
|
saved->properties = NULL;
|
||||||
|
|
||||||
return saved;
|
return saved;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,12 +351,201 @@ msm_session_get_failsafe (void)
|
|||||||
return msm_session_get_for_filename (_("Failsafe"), "Failsafe.session");
|
return msm_session_get_for_filename (_("Failsafe"), "Failsafe.session");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
write_proplist (FILE *fp,
|
||||||
|
GList *properties)
|
||||||
|
{
|
||||||
|
GList *tmp;
|
||||||
|
|
||||||
|
tmp = properties;
|
||||||
|
while (tmp != NULL)
|
||||||
|
{
|
||||||
|
SmProp *prop = tmp->data;
|
||||||
|
char *name_encoded;
|
||||||
|
char *type_encoded;
|
||||||
|
|
||||||
|
name_encoded = encode_text_as_utf8 (prop->name);
|
||||||
|
type_encoded = encode_text_as_utf8 (prop->type);
|
||||||
|
|
||||||
|
fprintf (fp, " <prop name=\"%s\" type=\"%s\">\n",
|
||||||
|
name_encoded, type_encoded);
|
||||||
|
|
||||||
|
g_free (name_encoded);
|
||||||
|
g_free (type_encoded);
|
||||||
|
|
||||||
|
if (strcmp (prop->type, SmCARD8) == 0)
|
||||||
|
{
|
||||||
|
int val = 0;
|
||||||
|
smprop_get_card8 (prop, &val);
|
||||||
|
fprintf (fp, " <value>%d</value>\n", val);
|
||||||
|
}
|
||||||
|
else if (strcmp (prop->type, SmARRAY8) == 0)
|
||||||
|
{
|
||||||
|
char *str = NULL;
|
||||||
|
char *encoded = NULL;
|
||||||
|
smprop_get_string (prop, &str);
|
||||||
|
if (str)
|
||||||
|
encoded = encode_text_as_utf8 (str);
|
||||||
|
if (encoded)
|
||||||
|
fprintf (fp, " <value>%s</value>\n", encoded);
|
||||||
|
|
||||||
|
g_free (encoded);
|
||||||
|
g_free (str);
|
||||||
|
}
|
||||||
|
else if (strcmp (prop->type, SmLISTofARRAY8) == 0)
|
||||||
|
{
|
||||||
|
char **vec;
|
||||||
|
int vec_len;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
vec = NULL;
|
||||||
|
vec_len = 0;
|
||||||
|
|
||||||
|
smprop_get_vector (prop, &vec_len, &vec);
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
while (i < vec_len)
|
||||||
|
{
|
||||||
|
char *encoded;
|
||||||
|
|
||||||
|
encoded = encode_text_as_utf8 (vec[i]);
|
||||||
|
|
||||||
|
fprintf (fp, " <value>%s</value>\n", encoded);
|
||||||
|
|
||||||
|
g_free (encoded);
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
|
||||||
|
g_strfreev (vec);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
msm_warning (_("Not saving unknown property type '%s'\n"),
|
||||||
|
prop->type);
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs (" </prop>\n", fp);
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
msm_session_save (MsmSession *session,
|
msm_session_save (MsmSession *session,
|
||||||
MsmServer *server)
|
MsmServer *server)
|
||||||
{
|
{
|
||||||
|
/* We save to a secondary file then copy over, to handle
|
||||||
|
* out-of-disk-space robustly
|
||||||
|
*/
|
||||||
|
int new_fd;
|
||||||
|
char *new_filename;
|
||||||
|
char *error;
|
||||||
|
FILE *fp;
|
||||||
|
|
||||||
|
error = NULL;
|
||||||
|
new_fd = -1;
|
||||||
|
|
||||||
|
new_filename = g_strconcat (session->full_filename, ".new", NULL);
|
||||||
|
new_fd = open (session->full_filename, O_RDWR | O_CREAT | O_EXCL, 0700);
|
||||||
|
if (new_fd < 0)
|
||||||
|
{
|
||||||
|
error = g_strdup_printf (_("Failed to open '%s': %s\n"),
|
||||||
|
new_filename, g_strerror (errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lock_entire_file (new_fd) < 0)
|
||||||
|
{
|
||||||
|
error = g_strdup_printf (_("Failed to lock file '%s': %s"),
|
||||||
|
new_filename,
|
||||||
|
g_strerror (errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fp = fdopen (new_fd, "w");
|
||||||
|
if (fp == NULL)
|
||||||
|
{
|
||||||
|
error = g_strdup_printf (_("Failed to write to new session file '%s': %s"),
|
||||||
|
new_filename, g_strerror (errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs ("<msm_session>\n", fp);
|
||||||
|
|
||||||
|
{
|
||||||
|
GList *tmp;
|
||||||
|
tmp = session->clients;
|
||||||
|
while (tmp != NULL)
|
||||||
|
{
|
||||||
|
MsmSavedClient *saved = tmp->data;
|
||||||
|
char *encoded;
|
||||||
|
|
||||||
|
encoded = encode_text_as_utf8 (saved->id);
|
||||||
|
|
||||||
|
fprintf (fp, " <client id=\"%s\">\n",
|
||||||
|
encoded);
|
||||||
|
|
||||||
|
g_free (encoded);
|
||||||
|
|
||||||
|
write_proplist (fp, saved->properties);
|
||||||
|
|
||||||
|
fputs (" </client>\n", fp);
|
||||||
|
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fputs ("</msm_session>\n", fp);
|
||||||
|
|
||||||
|
if (ferror (fp))
|
||||||
|
{
|
||||||
|
error = g_strdup_printf (_("Error writing new session file '%s': %s"),
|
||||||
|
new_filename, g_strerror (errno));
|
||||||
|
fclose (fp);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fclose (fp) < 0)
|
||||||
|
{
|
||||||
|
error = g_strdup_printf (_("Failed to close to new session file '%s': %s"),
|
||||||
|
new_filename, g_strerror (errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rename (new_filename, session->full_filename) < 0)
|
||||||
|
{
|
||||||
|
error = g_strdup_printf (_("Failed to replace the old session file '%s' with the new session contents in the temporary file '%s': %s"),
|
||||||
|
session->full_filename,
|
||||||
|
new_filename, g_strerror (errno));
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
out:
|
||||||
|
g_free (new_filename);
|
||||||
|
|
||||||
|
if (error)
|
||||||
|
{
|
||||||
|
if (new_fd >= 0)
|
||||||
|
close (new_fd);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (session->lock_fd >= 0)
|
||||||
|
close (session->lock_fd);
|
||||||
|
session->lock_fd = new_fd;
|
||||||
|
set_close_on_exec (new_fd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
add_details_to_dialog (GtkDialog *dialog,
|
||||||
|
const char *details)
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static MsmSession*
|
static MsmSession*
|
||||||
@ -368,21 +564,43 @@ recover_failed_session (MsmSession *session,
|
|||||||
case MSM_SESSION_FAILURE_OPENING_FILE:
|
case MSM_SESSION_FAILURE_OPENING_FILE:
|
||||||
message = g_strdup_printf (_("Could not open the session \"%s.\""),
|
message = g_strdup_printf (_("Could not open the session \"%s.\""),
|
||||||
session->name);
|
session->name);
|
||||||
|
/* FIXME recovery options:
|
||||||
|
* - give up and exit; something pathological is going on
|
||||||
|
* - choose another session?
|
||||||
|
* - use default session in read-only mode?
|
||||||
|
* - open xterm to repair the problem, then try again (experts only)
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSM_SESSION_FAILURE_LOCKING:
|
case MSM_SESSION_FAILURE_LOCKING:
|
||||||
message = g_strdup_printf (_("You are already logged in elsewhere, using the session \"%s.\" You can only use a session from one location at a time."),
|
message = g_strdup_printf (_("You are already logged in elsewhere, using the session \"%s.\" You can only use a session from one location at a time."),
|
||||||
session->name);
|
session->name);
|
||||||
|
/* FIXME recovery options:
|
||||||
|
* - log in anyhow, with possible weirdness
|
||||||
|
* - try again (after logging out the other session)
|
||||||
|
* - choose another session
|
||||||
|
* - open xterm to repair the problem, then try again (experts only)
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSM_SESSION_FAILURE_BAD_FILE:
|
case MSM_SESSION_FAILURE_BAD_FILE:
|
||||||
message = g_strdup_printf (_("The session file for session \"%s\" appears to be invalid or corrupted."),
|
message = g_strdup_printf (_("The session file for session \"%s\" appears to be invalid or corrupted."),
|
||||||
session->name);
|
session->name);
|
||||||
|
/* FIXME recovery options:
|
||||||
|
* - revert session to defaults
|
||||||
|
* - choose another session
|
||||||
|
* - open xterm to repair the problem, then try again (experts only)
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case MSM_SESSION_FAILURE_EMPTY:
|
case MSM_SESSION_FAILURE_EMPTY:
|
||||||
message = g_strdup_printf (_("The session \"%s\" contains no applications."),
|
message = g_strdup_printf (_("The session \"%s\" contains no applications."),
|
||||||
session->name);
|
session->name);
|
||||||
|
/* FIXME recovery options:
|
||||||
|
* - put default applications in the session
|
||||||
|
* - choose another session
|
||||||
|
* - open xterm to repair the problem, then try again (experts only)
|
||||||
|
*/
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -392,6 +610,9 @@ recover_failed_session (MsmSession *session,
|
|||||||
GTK_BUTTONS_CLOSE,
|
GTK_BUTTONS_CLOSE,
|
||||||
message);
|
message);
|
||||||
|
|
||||||
|
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
|
||||||
|
add_details_to_dialog (GTK_DIALOG (dialog), details);
|
||||||
|
|
||||||
g_free (message);
|
g_free (message);
|
||||||
|
|
||||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||||
@ -445,3 +666,46 @@ parse_session_file (MsmSession *session,
|
|||||||
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static char*
|
||||||
|
encode_text_as_utf8 (const char *text)
|
||||||
|
{
|
||||||
|
/* text can be any encoding, and is nul-terminated.
|
||||||
|
* we pretend it's Latin-1 and encode as UTF-8
|
||||||
|
*/
|
||||||
|
GString *str;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
str = g_string_new ("");
|
||||||
|
|
||||||
|
p = text;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
g_string_append_unichar (str, *p);
|
||||||
|
++p;
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_string_free (str, FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static char*
|
||||||
|
decode_text_from_utf8 (const char *text)
|
||||||
|
{
|
||||||
|
/* Convert back from the encoded UTF-8 */
|
||||||
|
GString *str;
|
||||||
|
const char *p;
|
||||||
|
|
||||||
|
str = g_string_new ("");
|
||||||
|
|
||||||
|
p = text;
|
||||||
|
while (*p)
|
||||||
|
{
|
||||||
|
/* obviously this barfs if the UTF-8 contains chars > 255 */
|
||||||
|
g_string_append_c (str, g_utf8_get_char (p));
|
||||||
|
|
||||||
|
p = g_utf8_next_char (p);
|
||||||
|
}
|
||||||
|
|
||||||
|
return g_string_free (str, FALSE);
|
||||||
|
}
|
||||||
|
@ -30,6 +30,8 @@
|
|||||||
/* should investigate changing these to whatever most apps use */
|
/* should investigate changing these to whatever most apps use */
|
||||||
#define META_ICON_WIDTH 32
|
#define META_ICON_WIDTH 32
|
||||||
#define META_ICON_HEIGHT 32
|
#define META_ICON_HEIGHT 32
|
||||||
|
#define META_MINI_ICON_WIDTH 16
|
||||||
|
#define META_MINI_ICON_HEIGHT 16
|
||||||
|
|
||||||
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
typedef void (* MetaScreenWindowFunc) (MetaScreen *screen, MetaWindow *window,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
@ -97,8 +97,8 @@ new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
|
|||||||
*/
|
*/
|
||||||
GIOChannel *channel;
|
GIOChannel *channel;
|
||||||
|
|
||||||
fcntl (IceConnectionNumber(connection),F_SETFD,
|
fcntl (IceConnectionNumber (connection), F_SETFD,
|
||||||
fcntl(IceConnectionNumber(connection),F_GETFD,0) | FD_CLOEXEC);
|
fcntl (IceConnectionNumber (connection), F_GETFD, 0) | FD_CLOEXEC);
|
||||||
|
|
||||||
channel = g_io_channel_unix_new (IceConnectionNumber (connection));
|
channel = g_io_channel_unix_new (IceConnectionNumber (connection));
|
||||||
|
|
||||||
@ -119,15 +119,15 @@ new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static IceIOErrorHandler gnome_ice_installed_handler;
|
static IceIOErrorHandler ice_installed_handler;
|
||||||
|
|
||||||
/* We call any handler installed before (or after) gnome_ice_init but
|
/* We call any handler installed before (or after) gnome_ice_init but
|
||||||
avoid calling the default libICE handler which does an exit() */
|
avoid calling the default libICE handler which does an exit() */
|
||||||
static void
|
static void
|
||||||
ice_io_error_handler (IceConn connection)
|
ice_io_error_handler (IceConn connection)
|
||||||
{
|
{
|
||||||
if (gnome_ice_installed_handler)
|
if (ice_installed_handler)
|
||||||
(*gnome_ice_installed_handler) (connection);
|
(*ice_installed_handler) (connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -139,11 +139,11 @@ ice_init (void)
|
|||||||
{
|
{
|
||||||
IceIOErrorHandler default_handler;
|
IceIOErrorHandler default_handler;
|
||||||
|
|
||||||
gnome_ice_installed_handler = IceSetIOErrorHandler (NULL);
|
ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||||
default_handler = IceSetIOErrorHandler (ice_io_error_handler);
|
default_handler = IceSetIOErrorHandler (ice_io_error_handler);
|
||||||
|
|
||||||
if (gnome_ice_installed_handler == default_handler)
|
if (ice_installed_handler == default_handler)
|
||||||
gnome_ice_installed_handler = NULL;
|
ice_installed_handler = NULL;
|
||||||
|
|
||||||
IceAddConnectionWatch (new_ice_connection, NULL);
|
IceAddConnectionWatch (new_ice_connection, NULL);
|
||||||
|
|
||||||
@ -879,11 +879,17 @@ save_state (void)
|
|||||||
out:
|
out:
|
||||||
if (outfile)
|
if (outfile)
|
||||||
{
|
{
|
||||||
if (fclose (outfile) != 0)
|
/* FIXME need a dialog for this */
|
||||||
|
if (ferror (outfile))
|
||||||
{
|
{
|
||||||
meta_warning (_("Error writing session file '%s': %s\n"),
|
meta_warning (_("Error writing session file '%s': %s\n"),
|
||||||
session_file, g_strerror (errno));
|
session_file, g_strerror (errno));
|
||||||
}
|
}
|
||||||
|
if (fclose (outfile))
|
||||||
|
{
|
||||||
|
meta_warning (_("Error closing session file '%s': %s\n"),
|
||||||
|
session_file, g_strerror (errno));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
g_free (metacity_dir);
|
g_free (metacity_dir);
|
||||||
|
10
src/ui.c
10
src/ui.c
@ -429,6 +429,16 @@ meta_ui_get_default_window_icon (MetaUI *ui)
|
|||||||
NULL);
|
NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
GdkPixbuf*
|
||||||
|
meta_ui_get_default_mini_icon (MetaUI *ui)
|
||||||
|
{
|
||||||
|
/* FIXME */
|
||||||
|
return gtk_widget_render_icon (GTK_WIDGET (ui->frames),
|
||||||
|
GTK_STOCK_NEW,
|
||||||
|
GTK_ICON_SIZE_MENU,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
|
||||||
gboolean
|
gboolean
|
||||||
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||||
Window xwindow)
|
Window xwindow)
|
||||||
|
1
src/ui.h
1
src/ui.h
@ -129,6 +129,7 @@ void meta_ui_push_delay_exposes (MetaUI *ui);
|
|||||||
void meta_ui_pop_delay_exposes (MetaUI *ui);
|
void meta_ui_pop_delay_exposes (MetaUI *ui);
|
||||||
|
|
||||||
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
|
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
|
||||||
|
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
|
||||||
|
|
||||||
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||||
Window xwindow);
|
Window xwindow);
|
||||||
|
142
src/window.c
142
src/window.c
@ -275,6 +275,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
|||||||
window->title = NULL;
|
window->title = NULL;
|
||||||
window->icon_name = NULL;
|
window->icon_name = NULL;
|
||||||
window->icon = NULL;
|
window->icon = NULL;
|
||||||
|
window->mini_icon = NULL;
|
||||||
|
|
||||||
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
|
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
|
||||||
|
|
||||||
@ -689,6 +690,9 @@ meta_window_free (MetaWindow *window)
|
|||||||
|
|
||||||
if (window->icon)
|
if (window->icon)
|
||||||
g_object_unref (G_OBJECT (window->icon));
|
g_object_unref (G_OBJECT (window->icon));
|
||||||
|
|
||||||
|
if (window->mini_icon)
|
||||||
|
g_object_unref (G_OBJECT (window->mini_icon));
|
||||||
|
|
||||||
g_free (window->sm_client_id);
|
g_free (window->sm_client_id);
|
||||||
g_free (window->role);
|
g_free (window->role);
|
||||||
@ -3808,6 +3812,8 @@ update_icon_name (MetaWindow *window)
|
|||||||
static gboolean
|
static gboolean
|
||||||
find_best_size (gulong *data,
|
find_best_size (gulong *data,
|
||||||
int nitems,
|
int nitems,
|
||||||
|
int ideal_width,
|
||||||
|
int ideal_height,
|
||||||
int *width,
|
int *width,
|
||||||
int *height,
|
int *height,
|
||||||
gulong **start)
|
gulong **start)
|
||||||
@ -3857,7 +3863,7 @@ find_best_size (gulong *data,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
/* work with averages */
|
/* work with averages */
|
||||||
const int ideal_size = META_ICON_WIDTH * META_ICON_HEIGHT;
|
const int ideal_size = (ideal_width + ideal_height) / 2;
|
||||||
int best_size = (best_w + best_h) / 2;
|
int best_size = (best_w + best_h) / 2;
|
||||||
int this_size = (w + h) / 2;
|
int this_size = (w + h) / 2;
|
||||||
|
|
||||||
@ -3875,7 +3881,7 @@ find_best_size (gulong *data,
|
|||||||
else if (best_size > ideal_size &&
|
else if (best_size > ideal_size &&
|
||||||
this_size >= ideal_size &&
|
this_size >= ideal_size &&
|
||||||
this_size < best_size)
|
this_size < best_size)
|
||||||
replace = TRUE;
|
replace = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (replace)
|
if (replace)
|
||||||
@ -3900,11 +3906,46 @@ find_best_size (gulong *data,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
argbdata_to_pixdata (gulong *argb_data, int len, guchar **pixdata)
|
||||||
|
{
|
||||||
|
guchar *p;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
*pixdata = g_new (guchar, len * 4);
|
||||||
|
p = *pixdata;
|
||||||
|
|
||||||
|
/* One could speed this up a lot. */
|
||||||
|
i = 0;
|
||||||
|
while (i < len)
|
||||||
|
{
|
||||||
|
guint argb;
|
||||||
|
guint rgba;
|
||||||
|
|
||||||
|
argb = argb_data[i];
|
||||||
|
rgba = (argb << 8) | (argb >> 24);
|
||||||
|
|
||||||
|
*p = rgba >> 24;
|
||||||
|
++p;
|
||||||
|
*p = (rgba >> 16) & 0xff;
|
||||||
|
++p;
|
||||||
|
*p = (rgba >> 8) & 0xff;
|
||||||
|
++p;
|
||||||
|
*p = rgba & 0xff;
|
||||||
|
++p;
|
||||||
|
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
read_rgb_icon (MetaWindow *window,
|
read_rgb_icon (MetaWindow *window,
|
||||||
int *width,
|
int *width,
|
||||||
int *height,
|
int *height,
|
||||||
guchar **pixdata)
|
guchar **pixdata,
|
||||||
|
int *mini_width,
|
||||||
|
int *mini_height,
|
||||||
|
guchar **mini_pixdata)
|
||||||
{
|
{
|
||||||
Atom type;
|
Atom type;
|
||||||
int format;
|
int format;
|
||||||
@ -3913,9 +3954,9 @@ read_rgb_icon (MetaWindow *window,
|
|||||||
int result;
|
int result;
|
||||||
gulong *data; /* FIXME should be guint? */
|
gulong *data; /* FIXME should be guint? */
|
||||||
gulong *best;
|
gulong *best;
|
||||||
int i;
|
|
||||||
int w, h;
|
int w, h;
|
||||||
guchar *p;
|
gulong *best_mini;
|
||||||
|
int mini_w, mini_h;
|
||||||
|
|
||||||
if (sizeof (gulong) != 4)
|
if (sizeof (gulong) != 4)
|
||||||
meta_warning ("%s: Whoops, I think this function may be broken on 64-bit\n",
|
meta_warning ("%s: Whoops, I think this function may be broken on 64-bit\n",
|
||||||
@ -3940,39 +3981,28 @@ read_rgb_icon (MetaWindow *window,
|
|||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!find_best_size (data, nitems, &w, &h, &best))
|
if (!find_best_size (data, nitems, META_ICON_WIDTH, META_ICON_HEIGHT,
|
||||||
|
&w, &h, &best))
|
||||||
{
|
{
|
||||||
XFree (data);
|
XFree (data);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!find_best_size (data, nitems, META_MINI_ICON_WIDTH, META_MINI_ICON_HEIGHT,
|
||||||
|
&mini_w, &mini_h, &best_mini))
|
||||||
|
{
|
||||||
|
XFree (data);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
*width = w;
|
*width = w;
|
||||||
*height = h;
|
*height = h;
|
||||||
|
|
||||||
*pixdata = g_new (guchar, w * h * 4);
|
*mini_width = mini_w;
|
||||||
p = *pixdata;
|
*mini_height = mini_h;
|
||||||
|
|
||||||
/* One could speed this up a lot. */
|
argbdata_to_pixdata (best, w * h, pixdata);
|
||||||
i = 0;
|
argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata);
|
||||||
while (i < w * h)
|
|
||||||
{
|
|
||||||
guint argb;
|
|
||||||
guint rgba;
|
|
||||||
|
|
||||||
argb = best[i];
|
|
||||||
rgba = (argb << 8) | (argb >> 24);
|
|
||||||
|
|
||||||
*p = rgba >> 24;
|
|
||||||
++p;
|
|
||||||
*p = (rgba >> 16) & 0xff;
|
|
||||||
++p;
|
|
||||||
*p = (rgba >> 8) & 0xff;
|
|
||||||
++p;
|
|
||||||
*p = rgba & 0xff;
|
|
||||||
++p;
|
|
||||||
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
XFree (data);
|
XFree (data);
|
||||||
|
|
||||||
@ -3987,6 +4017,12 @@ clear_icon (MetaWindow *window)
|
|||||||
g_object_unref (G_OBJECT (window->icon));
|
g_object_unref (G_OBJECT (window->icon));
|
||||||
window->icon = NULL;
|
window->icon = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window->mini_icon)
|
||||||
|
{
|
||||||
|
g_object_unref (G_OBJECT (window->mini_icon));
|
||||||
|
window->mini_icon = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -3997,7 +4033,8 @@ free_pixels (guchar *pixels, gpointer data)
|
|||||||
|
|
||||||
static void
|
static void
|
||||||
replace_icon (MetaWindow *window,
|
replace_icon (MetaWindow *window,
|
||||||
GdkPixbuf *unscaled)
|
GdkPixbuf *unscaled,
|
||||||
|
GdkPixbuf *unscaled_mini)
|
||||||
{
|
{
|
||||||
if (gdk_pixbuf_get_width (unscaled) != META_ICON_WIDTH ||
|
if (gdk_pixbuf_get_width (unscaled) != META_ICON_WIDTH ||
|
||||||
gdk_pixbuf_get_height (unscaled) != META_ICON_HEIGHT)
|
gdk_pixbuf_get_height (unscaled) != META_ICON_HEIGHT)
|
||||||
@ -4015,6 +4052,23 @@ replace_icon (MetaWindow *window,
|
|||||||
g_object_ref (G_OBJECT (unscaled));
|
g_object_ref (G_OBJECT (unscaled));
|
||||||
window->icon = unscaled;
|
window->icon = unscaled;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (gdk_pixbuf_get_width (unscaled_mini) != META_MINI_ICON_WIDTH ||
|
||||||
|
gdk_pixbuf_get_height (unscaled_mini) != META_MINI_ICON_HEIGHT)
|
||||||
|
{
|
||||||
|
/* FIXME should keep aspect ratio, but for now assuming
|
||||||
|
* a square source icon
|
||||||
|
*/
|
||||||
|
window->mini_icon = gdk_pixbuf_scale_simple (unscaled_mini,
|
||||||
|
META_MINI_ICON_WIDTH,
|
||||||
|
META_MINI_ICON_HEIGHT,
|
||||||
|
GDK_INTERP_BILINEAR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g_object_ref (G_OBJECT (unscaled_mini));
|
||||||
|
window->mini_icon = unscaled_mini;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -4149,7 +4203,7 @@ try_pixmap_and_mask (MetaWindow *window,
|
|||||||
|
|
||||||
if (unscaled)
|
if (unscaled)
|
||||||
{
|
{
|
||||||
replace_icon (window, unscaled);
|
replace_icon (window, unscaled, unscaled);
|
||||||
g_object_unref (G_OBJECT (unscaled));
|
g_object_unref (G_OBJECT (unscaled));
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
@ -4162,18 +4216,22 @@ update_icon (MetaWindow *window,
|
|||||||
gboolean reload_rgb_icon)
|
gboolean reload_rgb_icon)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (FALSE && reload_rgb_icon)
|
if (reload_rgb_icon)
|
||||||
{
|
{
|
||||||
guchar *pixdata;
|
guchar *pixdata;
|
||||||
int w, h;
|
int w, h;
|
||||||
|
guchar *mini_pixdata;
|
||||||
|
int mini_w, mini_h;
|
||||||
|
|
||||||
pixdata = NULL;
|
pixdata = NULL;
|
||||||
|
|
||||||
if (read_rgb_icon (window, &w, &h, &pixdata))
|
if (read_rgb_icon (window, &w, &h, &pixdata,
|
||||||
|
&mini_w, &mini_h, &mini_pixdata))
|
||||||
{
|
{
|
||||||
GdkPixbuf *unscaled;
|
GdkPixbuf *unscaled;
|
||||||
|
GdkPixbuf *unscaled_mini;
|
||||||
|
|
||||||
meta_verbose ("successfully read RGBA icon from _NET_WM_ICON, using w = %d h = %d\n", w, h);
|
meta_verbose ("successfully read RGBA icon from _NET_WM_ICON, using w = %d h = %d mini_w = %d mini_h = %d\n", w, h, mini_w, mini_h);
|
||||||
|
|
||||||
window->using_rgb_icon = TRUE;
|
window->using_rgb_icon = TRUE;
|
||||||
|
|
||||||
@ -4185,9 +4243,18 @@ update_icon (MetaWindow *window,
|
|||||||
free_pixels,
|
free_pixels,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
replace_icon (window, unscaled);
|
unscaled_mini = gdk_pixbuf_new_from_data (mini_pixdata,
|
||||||
|
GDK_COLORSPACE_RGB,
|
||||||
|
TRUE,
|
||||||
|
8,
|
||||||
|
mini_w, mini_h, mini_w * 4,
|
||||||
|
free_pixels,
|
||||||
|
NULL);
|
||||||
|
|
||||||
|
replace_icon (window, unscaled, unscaled_mini);
|
||||||
|
|
||||||
g_object_unref (G_OBJECT (unscaled));
|
g_object_unref (G_OBJECT (unscaled));
|
||||||
|
g_object_unref (G_OBJECT (unscaled_mini));
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
@ -4237,7 +4304,10 @@ update_icon (MetaWindow *window,
|
|||||||
|
|
||||||
/* Fallback to a default icon */
|
/* Fallback to a default icon */
|
||||||
if (window->icon == NULL)
|
if (window->icon == NULL)
|
||||||
window->icon = meta_ui_get_default_window_icon (window->screen->ui);
|
{
|
||||||
|
window->icon = meta_ui_get_default_window_icon (window->screen->ui);
|
||||||
|
window->mini_icon = meta_ui_get_default_mini_icon (window->screen->ui);
|
||||||
|
}
|
||||||
|
|
||||||
return Success;
|
return Success;
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ struct _MetaWindow
|
|||||||
|
|
||||||
char *icon_name;
|
char *icon_name;
|
||||||
GdkPixbuf *icon;
|
GdkPixbuf *icon;
|
||||||
|
GdkPixbuf *mini_icon;
|
||||||
|
|
||||||
MetaWindowType type;
|
MetaWindowType type;
|
||||||
Atom type_atom;
|
Atom type_atom;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user