mirror of
https://github.com/brl/mutter.git
synced 2024-11-21 23:50:41 -05:00
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>
|
||||
|
||||
* 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)
|
||||
fi
|
||||
|
||||
# Check for shaped window extension
|
||||
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
||||
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "true")
|
||||
|
||||
MSM_CFLAGS=$METACITY_CFLAGS
|
||||
MSM_LIBS=$METACITY_LIBS
|
||||
|
||||
AC_SUBST(MSM_CFLAGS)
|
||||
AC_SUBST(MSM_LIBS)
|
||||
|
||||
HOST_ALIAS=$host_alias
|
||||
AC_SUBST(HOST_ALIAS)
|
||||
@ -72,6 +77,7 @@ AC_OUTPUT([
|
||||
Makefile
|
||||
src/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@\"
|
||||
|
||||
|
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);
|
||||
}
|
||||
|
||||
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
|
||||
meta_core_queue_frame_resize (Display *xdisplay,
|
||||
Window frame_xwindow)
|
||||
|
@ -36,6 +36,9 @@ void meta_core_get_frame_size (Display *xdisplay,
|
||||
MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
GdkPixbuf* meta_core_get_mini_icon (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
void meta_core_queue_frame_resize (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
|
71
src/frames.c
71
src/frames.c
@ -1740,11 +1740,78 @@ meta_frames_expose_event (GtkWidget *widget,
|
||||
|
||||
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);
|
||||
|
||||
{
|
||||
/* 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,
|
||||
layout_gc,
|
||||
fgeom.title_rect.x + frames->props->text_border.left,
|
||||
fgeom.title_rect.y + frames->props->text_border.top,
|
||||
x, y,
|
||||
frame->layout);
|
||||
gdk_gc_set_clip_rectangle (layout_gc, NULL);
|
||||
}
|
||||
|
@ -42,7 +42,7 @@ static void
|
||||
usage (void)
|
||||
{
|
||||
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n");
|
||||
exit (0);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -288,25 +288,9 @@ msm_client_set_property_taking_ownership (MsmClient *client,
|
||||
SmProp *prop)
|
||||
{
|
||||
/* we own prop which should be freed with SmFreeProperty() */
|
||||
GList *list;
|
||||
|
||||
if (prop->name == NULL)
|
||||
{
|
||||
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);
|
||||
}
|
||||
/* pass our ownership into the proplist */
|
||||
client->properties = proplist_replace (client->properties, prop);
|
||||
|
||||
/* update pieces of the client struct */
|
||||
if (strcmp (prop->name, "SmRestartStyleHint") == 0)
|
||||
@ -323,15 +307,7 @@ void
|
||||
msm_client_unset_property (MsmClient *client,
|
||||
const char *name)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
list = proplist_find_link_by_name (client->properties, name);
|
||||
if (list)
|
||||
{
|
||||
SmFreeProperty (list->data);
|
||||
client->properties = g_list_delete_link (client->properties,
|
||||
list);
|
||||
}
|
||||
client->properties = proplist_delete (client->properties, name);
|
||||
|
||||
/* Return to default values */
|
||||
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);
|
||||
}
|
||||
|
||||
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
|
||||
proplist_find_vector (GList *list, const char *name,
|
||||
int *argcp, char ***argvp)
|
||||
@ -206,5 +280,72 @@ smprop_copy (SmProp *prop)
|
||||
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,
|
||||
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,
|
||||
int *result);
|
||||
gboolean smprop_get_string (SmProp *prop,
|
||||
@ -49,6 +67,16 @@ gboolean smprop_get_vector (SmProp *prop,
|
||||
int *argcp,
|
||||
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);
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
@ -38,7 +39,7 @@ typedef struct _MsmSavedClient MsmSavedClient;
|
||||
struct _MsmSavedClient
|
||||
{
|
||||
char *id;
|
||||
|
||||
GList *properties;
|
||||
};
|
||||
|
||||
struct _MsmSession
|
||||
@ -71,6 +72,9 @@ static MsmSession* recover_failed_session (MsmSession *session,
|
||||
static gboolean parse_session_file (MsmSession *session,
|
||||
GError **error);
|
||||
|
||||
static char* decode_text_from_utf8 (const char *text);
|
||||
static char* encode_text_as_utf8 (const char *text);
|
||||
|
||||
void
|
||||
msm_session_clear (MsmSession *session)
|
||||
{
|
||||
@ -106,8 +110,10 @@ msm_session_client_id_known (MsmSession *session,
|
||||
void
|
||||
msm_session_launch (MsmSession *session)
|
||||
{
|
||||
|
||||
|
||||
system ("xclock &");
|
||||
system ("xclock &");
|
||||
system ("xclock &");
|
||||
system ("xterm &");
|
||||
}
|
||||
|
||||
MsmSavedClient*
|
||||
@ -118,6 +124,7 @@ saved_new (void)
|
||||
saved = g_new (MsmSavedClient, 1);
|
||||
|
||||
saved->id = NULL;
|
||||
saved->properties = NULL;
|
||||
|
||||
return saved;
|
||||
}
|
||||
@ -344,10 +351,199 @@ msm_session_get_failsafe (void)
|
||||
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
|
||||
msm_session_save (MsmSession *session,
|
||||
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)
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
@ -368,21 +564,43 @@ recover_failed_session (MsmSession *session,
|
||||
case MSM_SESSION_FAILURE_OPENING_FILE:
|
||||
message = g_strdup_printf (_("Could not open the session \"%s.\""),
|
||||
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;
|
||||
|
||||
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."),
|
||||
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;
|
||||
|
||||
case MSM_SESSION_FAILURE_BAD_FILE:
|
||||
message = g_strdup_printf (_("The session file for session \"%s\" appears to be invalid or corrupted."),
|
||||
session->name);
|
||||
/* FIXME recovery options:
|
||||
* - revert session to defaults
|
||||
* - choose another session
|
||||
* - open xterm to repair the problem, then try again (experts only)
|
||||
*/
|
||||
break;
|
||||
|
||||
case MSM_SESSION_FAILURE_EMPTY:
|
||||
message = g_strdup_printf (_("The session \"%s\" contains no applications."),
|
||||
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;
|
||||
}
|
||||
|
||||
@ -392,6 +610,9 @@ recover_failed_session (MsmSession *session,
|
||||
GTK_BUTTONS_CLOSE,
|
||||
message);
|
||||
|
||||
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
|
||||
add_details_to_dialog (GTK_DIALOG (dialog), details);
|
||||
|
||||
g_free (message);
|
||||
|
||||
gtk_dialog_run (GTK_DIALOG (dialog));
|
||||
@ -445,3 +666,46 @@ parse_session_file (MsmSession *session,
|
||||
|
||||
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 */
|
||||
#define META_ICON_WIDTH 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,
|
||||
gpointer user_data);
|
||||
|
@ -97,8 +97,8 @@ new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
|
||||
*/
|
||||
GIOChannel *channel;
|
||||
|
||||
fcntl (IceConnectionNumber(connection),F_SETFD,
|
||||
fcntl(IceConnectionNumber(connection),F_GETFD,0) | FD_CLOEXEC);
|
||||
fcntl (IceConnectionNumber (connection), F_SETFD,
|
||||
fcntl (IceConnectionNumber (connection), F_GETFD, 0) | FD_CLOEXEC);
|
||||
|
||||
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
|
||||
avoid calling the default libICE handler which does an exit() */
|
||||
static void
|
||||
ice_io_error_handler (IceConn connection)
|
||||
{
|
||||
if (gnome_ice_installed_handler)
|
||||
(*gnome_ice_installed_handler) (connection);
|
||||
if (ice_installed_handler)
|
||||
(*ice_installed_handler) (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -139,11 +139,11 @@ ice_init (void)
|
||||
{
|
||||
IceIOErrorHandler default_handler;
|
||||
|
||||
gnome_ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||
ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||
default_handler = IceSetIOErrorHandler (ice_io_error_handler);
|
||||
|
||||
if (gnome_ice_installed_handler == default_handler)
|
||||
gnome_ice_installed_handler = NULL;
|
||||
if (ice_installed_handler == default_handler)
|
||||
ice_installed_handler = NULL;
|
||||
|
||||
IceAddConnectionWatch (new_ice_connection, NULL);
|
||||
|
||||
@ -879,11 +879,17 @@ save_state (void)
|
||||
out:
|
||||
if (outfile)
|
||||
{
|
||||
if (fclose (outfile) != 0)
|
||||
/* FIXME need a dialog for this */
|
||||
if (ferror (outfile))
|
||||
{
|
||||
meta_warning (_("Error writing session file '%s': %s\n"),
|
||||
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);
|
||||
|
10
src/ui.c
10
src/ui.c
@ -429,6 +429,16 @@ meta_ui_get_default_window_icon (MetaUI *ui)
|
||||
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
|
||||
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
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);
|
||||
|
||||
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,
|
||||
Window xwindow);
|
||||
|
138
src/window.c
138
src/window.c
@ -275,6 +275,7 @@ meta_window_new (MetaDisplay *display, Window xwindow,
|
||||
window->title = NULL;
|
||||
window->icon_name = NULL;
|
||||
window->icon = NULL;
|
||||
window->mini_icon = NULL;
|
||||
|
||||
window->desc = g_strdup_printf ("0x%lx", window->xwindow);
|
||||
|
||||
@ -690,6 +691,9 @@ meta_window_free (MetaWindow *window)
|
||||
if (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->role);
|
||||
g_free (window->res_class);
|
||||
@ -3808,6 +3812,8 @@ update_icon_name (MetaWindow *window)
|
||||
static gboolean
|
||||
find_best_size (gulong *data,
|
||||
int nitems,
|
||||
int ideal_width,
|
||||
int ideal_height,
|
||||
int *width,
|
||||
int *height,
|
||||
gulong **start)
|
||||
@ -3857,7 +3863,7 @@ find_best_size (gulong *data,
|
||||
else
|
||||
{
|
||||
/* 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 this_size = (w + h) / 2;
|
||||
|
||||
@ -3900,11 +3906,46 @@ find_best_size (gulong *data,
|
||||
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
|
||||
read_rgb_icon (MetaWindow *window,
|
||||
int *width,
|
||||
int *height,
|
||||
guchar **pixdata)
|
||||
guchar **pixdata,
|
||||
int *mini_width,
|
||||
int *mini_height,
|
||||
guchar **mini_pixdata)
|
||||
{
|
||||
Atom type;
|
||||
int format;
|
||||
@ -3913,9 +3954,9 @@ read_rgb_icon (MetaWindow *window,
|
||||
int result;
|
||||
gulong *data; /* FIXME should be guint? */
|
||||
gulong *best;
|
||||
int i;
|
||||
int w, h;
|
||||
guchar *p;
|
||||
gulong *best_mini;
|
||||
int mini_w, mini_h;
|
||||
|
||||
if (sizeof (gulong) != 4)
|
||||
meta_warning ("%s: Whoops, I think this function may be broken on 64-bit\n",
|
||||
@ -3940,7 +3981,15 @@ read_rgb_icon (MetaWindow *window,
|
||||
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);
|
||||
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;
|
||||
@ -3949,30 +3998,11 @@ read_rgb_icon (MetaWindow *window,
|
||||
*width = w;
|
||||
*height = h;
|
||||
|
||||
*pixdata = g_new (guchar, w * h * 4);
|
||||
p = *pixdata;
|
||||
*mini_width = mini_w;
|
||||
*mini_height = mini_h;
|
||||
|
||||
/* One could speed this up a lot. */
|
||||
i = 0;
|
||||
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;
|
||||
}
|
||||
argbdata_to_pixdata (best, w * h, pixdata);
|
||||
argbdata_to_pixdata (best_mini, mini_w * mini_h, mini_pixdata);
|
||||
|
||||
XFree (data);
|
||||
|
||||
@ -3987,6 +4017,12 @@ clear_icon (MetaWindow *window)
|
||||
g_object_unref (G_OBJECT (window->icon));
|
||||
window->icon = NULL;
|
||||
}
|
||||
|
||||
if (window->mini_icon)
|
||||
{
|
||||
g_object_unref (G_OBJECT (window->mini_icon));
|
||||
window->mini_icon = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
@ -3997,7 +4033,8 @@ free_pixels (guchar *pixels, gpointer data)
|
||||
|
||||
static void
|
||||
replace_icon (MetaWindow *window,
|
||||
GdkPixbuf *unscaled)
|
||||
GdkPixbuf *unscaled,
|
||||
GdkPixbuf *unscaled_mini)
|
||||
{
|
||||
if (gdk_pixbuf_get_width (unscaled) != META_ICON_WIDTH ||
|
||||
gdk_pixbuf_get_height (unscaled) != META_ICON_HEIGHT)
|
||||
@ -4015,6 +4052,23 @@ replace_icon (MetaWindow *window,
|
||||
g_object_ref (G_OBJECT (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
|
||||
@ -4149,7 +4203,7 @@ try_pixmap_and_mask (MetaWindow *window,
|
||||
|
||||
if (unscaled)
|
||||
{
|
||||
replace_icon (window, unscaled);
|
||||
replace_icon (window, unscaled, unscaled);
|
||||
g_object_unref (G_OBJECT (unscaled));
|
||||
return TRUE;
|
||||
}
|
||||
@ -4162,18 +4216,22 @@ update_icon (MetaWindow *window,
|
||||
gboolean reload_rgb_icon)
|
||||
{
|
||||
|
||||
if (FALSE && reload_rgb_icon)
|
||||
if (reload_rgb_icon)
|
||||
{
|
||||
guchar *pixdata;
|
||||
int w, h;
|
||||
guchar *mini_pixdata;
|
||||
int mini_w, mini_h;
|
||||
|
||||
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_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;
|
||||
|
||||
@ -4185,9 +4243,18 @@ update_icon (MetaWindow *window,
|
||||
free_pixels,
|
||||
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_mini));
|
||||
|
||||
return Success;
|
||||
}
|
||||
@ -4237,7 +4304,10 @@ update_icon (MetaWindow *window,
|
||||
|
||||
/* Fallback to a default icon */
|
||||
if (window->icon == NULL)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
@ -55,6 +55,7 @@ struct _MetaWindow
|
||||
|
||||
char *icon_name;
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
|
||||
MetaWindowType type;
|
||||
Atom type_atom;
|
||||
|
Loading…
Reference in New Issue
Block a user