I've got a patch to add rounded corners back to gnome-panel. The only applet I've found that this malfunctions with is the show desktop applet, but the fix for that is 1 line long as shown in some of the other applets that are in gnome-panel. The reason I didn't include it here is that it's in a different module. Also included are the required images. They go in icons/ Let me know if anyone finds any bugs with these, including applets that don't work if you put them in the corner. Mark, I looked at moving this into a separate file, but some of it just can't be done. If you have any specific bits you want me to look at separating out, let me know. If you want me to commit this, I'll write a good ChangeLog entry and then do so. Let me know. Thanks, Chris
Attachment:
panel-corner-bottom-left.png
Description: PNG image
Attachment:
panel-corner-bottom-right.png
Description: PNG image
Attachment:
panel-corner-top-left.png
Description: PNG image
Attachment:
panel-corner-top-right.png
Description: PNG image
Index: applets/clock/clock.c =================================================================== RCS file: /cvs/gnome/gnome-panel/applets/clock/clock.c,v retrieving revision 1.117 diff -u -p -r1.117 clock.c --- applets/clock/clock.c 13 Nov 2003 00:21:45 -0000 1.117 +++ applets/clock/clock.c 13 Nov 2003 20:42:15 -0000 @@ -1218,7 +1218,9 @@ fill_clock_applet (PanelApplet *applet) "hidden", "1", NULL); } - + + panel_applet_set_stretch_widget (applet, cd->toggle); + return TRUE; } Index: applets/wncklet/workspace-switcher.c =================================================================== RCS file: /cvs/gnome/gnome-panel/applets/wncklet/workspace-switcher.c,v retrieving revision 1.60 diff -u -p -r1.60 workspace-switcher.c --- applets/wncklet/workspace-switcher.c 14 Oct 2003 20:28:37 -0000 1.60 +++ applets/wncklet/workspace-switcher.c 13 Nov 2003 20:42:15 -0000 @@ -447,6 +447,8 @@ workspace_switcher_applet_fill (PanelApp NULL); } + panel_applet_set_stretch_widget (PANEL_APPLET (pager->applet), pager->pager); + return TRUE; } Index: gnome-panel/panel-applet-frame.c =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-applet-frame.c,v retrieving revision 1.113 diff -u -p -r1.113 panel-applet-frame.c --- gnome-panel/panel-applet-frame.c 13 Nov 2003 12:31:02 -0000 1.113 +++ gnome-panel/panel-applet-frame.c 13 Nov 2003 20:42:15 -0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * panel-applet-frame.c: panel side container for applets * @@ -53,6 +54,8 @@ #define PROPERTY_FLAGS "panel-applet-flags" #define PROPERTY_SIZE_HINTS "panel-applet-size-hints" #define PROPERTY_LOCKED_DOWN "panel-applet-locked-down" +#define PROPERTY_TOPLEVEL_WINDOW "panel-applet-toplevel-window" +#define PROPERTY_STRETCH_FLAGS "panel-applet-stretch-flags" struct _PanelAppletFramePrivate { @@ -70,6 +73,8 @@ struct _PanelAppletFramePrivate { GtkAllocation child_allocation; GdkRectangle handle_rect; + PanelStretchFlags stretch_flags; + guint has_handle : 1; }; @@ -697,19 +702,25 @@ panel_applet_frame_button_changed (GtkWi { PanelAppletFrame *frame; gboolean handled = FALSE; + GdkWindow *stretch_window; frame = PANEL_APPLET_FRAME (widget); if (!frame->priv->has_handle) return handled; - if (event->window != widget->window) + stretch_window = g_object_get_data (G_OBJECT (widget), "StretchEventWindow"); + + if (event->window != widget->window && + event->window != stretch_window) { return FALSE; + } switch (event->button) { case 1: case 2: - if (button_event_in_rect (event, &frame->priv->handle_rect)) { + if (stretch_window == event->window || + button_event_in_rect (event, &frame->priv->handle_rect)) { if (event->type == GDK_BUTTON_PRESS || event->type == GDK_2BUTTON_PRESS) { panel_widget_applet_drag_start ( @@ -1358,4 +1369,59 @@ panel_applet_frame_set_panel (PanelApple g_return_if_fail (PANEL_IS_WIDGET (panel)); frame->priv->panel = panel; +} + +void +panel_applet_frame_set_stretch_flags (PanelAppletFrame *frame, + PanelStretchFlags flags) +{ + GtkWidget *toplevel; + if (flags == frame->priv->stretch_flags) + return; + if (frame->priv->has_handle) { + /* If the applet either did touch the left, or will + now, we have to call stretch events on the frame + itself to handle the handle. */ + if ((frame->priv->stretch_flags & PANEL_STRETCH_LEFT) || + (flags & PANEL_STRETCH_LEFT)) { + if (flags & PANEL_STRETCH_LEFT) { + /* If it will touch the left now, just + call panel_stretch_events */ + panel_stretch_events_to_toplevel (GTK_WIDGET (frame), flags); + } else { + /* But if it won't, then we just want + to unstretch it since it used to + touch the left. */ + panel_stretch_events_to_toplevel (GTK_WIDGET (frame), PANEL_STRETCH_NONE); + } + } + + if (!((frame->priv->stretch_flags & PANEL_STRETCH_RIGHT) || + (flags & PANEL_STRETCH_RIGHT))) { + /* If it both didn't touch the right and will + still not now touch the right, we're done. + Set the field and return. */ + frame->priv->stretch_flags = flags; + return; + } + if (!(flags & PANEL_STRETCH_RIGHT)) { + /* If it won't touch the right now, then it + used to, so we just want to unstretch the + child applet. */ + flags = PANEL_STRETCH_NONE; + } + } + + /* Pass the settings on to the child applet. */ + frame->priv->stretch_flags = flags; + + toplevel = gtk_widget_get_toplevel (GTK_WIDGET (frame)); + bonobo_pbclient_set_long (frame->priv->property_bag, + PROPERTY_TOPLEVEL_WINDOW, + gdk_x11_drawable_get_xid (toplevel->window), + NULL); + bonobo_pbclient_set_short (frame->priv->property_bag, + PROPERTY_STRETCH_FLAGS, + flags, + NULL); } Index: gnome-panel/panel-applet-frame.h =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-applet-frame.h,v retrieving revision 1.33 diff -u -p -r1.33 panel-applet-frame.h --- gnome-panel/panel-applet-frame.h 26 May 2003 13:41:07 -0000 1.33 +++ gnome-panel/panel-applet-frame.h 13 Nov 2003 20:42:15 -0000 @@ -28,6 +28,7 @@ #include <gtk/gtkeventbox.h> #include "panel-widget.h" +#include "panel-util.h" #include "applet.h" G_BEGIN_DECLS @@ -91,6 +92,9 @@ int panel_applet_frame_get_size_h void panel_applet_frame_set_panel (PanelAppletFrame *frame, PanelWidget *panel); PanelWidget *panel_applet_frame_get_panel (PanelAppletFrame *frame); + +void panel_applet_frame_set_stretch_flags (PanelAppletFrame *frame, + PanelStretchFlags flags); G_END_DECLS Index: gnome-panel/panel-toplevel.c =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-toplevel.c,v retrieving revision 1.45 diff -u -p -r1.45 panel-toplevel.c --- gnome-panel/panel-toplevel.c 13 Nov 2003 13:09:06 -0000 1.45 +++ gnome-panel/panel-toplevel.c 13 Nov 2003 20:42:15 -0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * panel-toplevel.c: The panel's toplevel window object. * @@ -44,7 +45,10 @@ #include "panel-widget.h" #include "panel-bindings.h" #include "panel-struts.h" +#include "panel-util.h" #include "xstuff.h" +#include "panel-menu-bar.h" +#include "panel-applet-frame.h" #define PANEL_TOPLEVEL_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_TOPLEVEL, PanelToplevelPrivate)) @@ -131,6 +135,20 @@ struct _PanelToplevelPrivate { GtkWidget *hide_button_left; GtkWidget *hide_button_right; + GtkWidget *corner_top_left_horizontal; + GtkWidget *corner_top_right_horizontal; + GtkWidget *corner_bottom_left_horizontal; + GtkWidget *corner_bottom_right_horizontal; + GtkWidget *corner_top_left_vertical; + GtkWidget *corner_bottom_left_vertical; + GtkWidget *corner_top_right_vertical; + GtkWidget *corner_bottom_right_vertical; + + GtkWidget *extended_widget_at_start; + GtkWidget *extended_widget_at_end; + PanelStretchFlags extended_flags_at_start; + PanelStretchFlags extended_flags_at_end; + PanelToplevel *attach_toplevel; gulong attach_toplevel_signals [N_ATTACH_TOPLEVEL_SIGNALS]; GtkWidget *attach_widget; @@ -1090,6 +1108,54 @@ panel_toplevel_hide_button_clicked (Pane } static GtkWidget * +panel_toplevel_add_rounded_corner (PanelToplevel *toplevel, + int left_attach, + int right_attach, + int top_attach, + int bottom_attach) +{ + char *path; + char *filename; + GtkWidget *align = NULL; + GtkWidget *image; + gboolean left = FALSE; + gboolean top = FALSE; + gboolean horizontal = FALSE; + + if (left_attach < 3) + left = TRUE; + if (top_attach < 3) + top = TRUE; + if (left_attach == 0 || left_attach == 4) + horizontal = TRUE; + + filename = g_strdup_printf ("panel-corner-%s-%s.png", top ? "top" : "bottom", left ? "left" : "right"); + path = panel_pixmap_discovery (filename, FALSE /* fallback */); + if (path != NULL) { + image = gtk_image_new_from_file (path); + g_free (path); + align = gtk_alignment_new (left ? 0.0 : 1.0, top ? 0.0 : 1.0, 0.0, 0.0); + gtk_container_add (GTK_CONTAINER (align), image); + + gtk_table_attach (GTK_TABLE (toplevel->priv->table), + align, + left_attach, + right_attach, + top_attach, + bottom_attach, + GTK_FILL, + GTK_FILL, + 0, + 0); + gtk_widget_show (image); + gtk_widget_show (align); + } + g_free (filename); + + return align; +} + +static GtkWidget * panel_toplevel_add_hide_button (PanelToplevel *toplevel, GtkArrowType arrow_type, int left_attach, @@ -1099,21 +1165,26 @@ panel_toplevel_add_hide_button (PanelTop { GtkWidget *button; GtkWidget *arrow; + gboolean horizontal = FALSE; button = gtk_button_new (); GTK_WIDGET_UNSET_FLAGS (button, GTK_CAN_DEFAULT); switch (arrow_type) { case GTK_ARROW_UP: + horizontal = FALSE; gtk_widget_set_size_request (button, -1, HIDE_BUTTON_SIZE); break; case GTK_ARROW_DOWN: + horizontal = FALSE; gtk_widget_set_size_request (button, -1, HIDE_BUTTON_SIZE); break; case GTK_ARROW_LEFT: + horizontal = TRUE; gtk_widget_set_size_request (button, HIDE_BUTTON_SIZE, -1); break; case GTK_ARROW_RIGHT: + horizontal = TRUE; gtk_widget_set_size_request (button, HIDE_BUTTON_SIZE, -1); break; default: @@ -1146,8 +1217,8 @@ panel_toplevel_add_hide_button (PanelTop right_attach, top_attach, bottom_attach, - GTK_FILL, - GTK_FILL, + GTK_FILL | (horizontal ? 0 : GTK_EXPAND), + GTK_FILL | (horizontal ? GTK_EXPAND : 0), 0, 0); @@ -1191,6 +1262,267 @@ panel_toplevel_update_buttons_showing (P } static void +at_start_weak_ref (gpointer data, GObject *where_object_was) +{ + PanelToplevel *toplevel = data; + toplevel->priv->extended_widget_at_start = NULL; + toplevel->priv->extended_flags_at_start = PANEL_STRETCH_NONE; +} + +static void +at_end_weak_ref (gpointer data, GObject *where_object_was) +{ + PanelToplevel *toplevel = data; + toplevel->priv->extended_widget_at_end = NULL; + toplevel->priv->extended_flags_at_end = PANEL_STRETCH_NONE; +} + +static void +create_extension (PanelToplevel *toplevel, gboolean at_start) +{ + GtkWidget *widget; + PanelStretchFlags flags; + if (at_start) { + widget = toplevel->priv->extended_widget_at_start; + flags = toplevel->priv->extended_flags_at_start; + } else { + widget = toplevel->priv->extended_widget_at_end; + flags = toplevel->priv->extended_flags_at_end; + } + if (widget == NULL) + return; + if (PANEL_IS_MENU_BAR (widget)) { + GList *children; + children = gtk_container_get_children (GTK_CONTAINER(widget)); + if (children) { + if (children->next == NULL) { + panel_stretch_events_to_toplevel (children->data, flags); + } else { + panel_stretch_events_to_toplevel (children->data, flags & ~PANEL_STRETCH_RIGHT); + children = children->next; + while (children) { + if (children->next) + panel_stretch_events_to_toplevel (children->data, flags & ~PANEL_STRETCH_LEFT & ~PANEL_STRETCH_RIGHT); + else + panel_stretch_events_to_toplevel (children->data, flags & ~PANEL_STRETCH_LEFT); + children = children->next; + } + } + } + } else if (BUTTON_IS_WIDGET (widget)) { + panel_stretch_events_to_toplevel (widget, flags); + } else if (PANEL_IS_APPLET_FRAME (widget)) { + panel_applet_frame_set_stretch_flags (PANEL_APPLET_FRAME (widget), flags); + } + + if (at_start) { + g_object_weak_ref (G_OBJECT (widget), at_start_weak_ref, toplevel); + } else { + g_object_weak_ref (G_OBJECT (widget), at_end_weak_ref, toplevel); + } +} + +static void +cancel_extension (PanelToplevel *toplevel, gboolean at_start) +{ + GtkWidget *widget; + if (at_start) { + widget = toplevel->priv->extended_widget_at_start; + } else { + widget = toplevel->priv->extended_widget_at_end; + } + if (widget == NULL) + return; + if (at_start) { + g_object_weak_unref (G_OBJECT (widget), at_start_weak_ref, toplevel); + } else { + g_object_weak_unref (G_OBJECT (widget), at_end_weak_ref, toplevel); + } + if (PANEL_IS_MENU_BAR (widget)) { + GList *children; + children = gtk_container_get_children (GTK_CONTAINER(widget)); + while (children) { + panel_stretch_events_to_toplevel (children->data, PANEL_STRETCH_NONE); + children = children->next; + } + } else if (BUTTON_IS_WIDGET (widget)) { + panel_stretch_events_to_toplevel (widget, PANEL_STRETCH_NONE); + } else if (PANEL_IS_APPLET_FRAME (widget)) { + panel_applet_frame_set_stretch_flags (PANEL_APPLET_FRAME (widget), PANEL_STRETCH_NONE); + } +} + +static void +panel_toplevel_update_extends (PanelToplevel *toplevel) +{ + int monitor_width, monitor_height; + int width, height; + AppletData *ad_start = NULL; + AppletData *ad_end = NULL; + GtkWidget *widget_start = NULL; + GtkWidget *widget_end = NULL; + PanelStretchFlags flags_start = 0, flags_end = 0; + + if (!toplevel->priv->buttons_enabled && + !toplevel->priv->auto_hide && + toplevel->priv->expand) { + panel_toplevel_get_monitor_geometry ( + toplevel, NULL, NULL, &monitor_width, &monitor_height); + + width = toplevel->priv->geometry.width; + height = toplevel->priv->geometry.height; + + switch (toplevel->priv->orientation) { + case PANEL_ORIENTATION_LEFT: + flags_start = PANEL_STRETCH_TOP | PANEL_STRETCH_LEFT; + flags_end = PANEL_STRETCH_BOTTOM | PANEL_STRETCH_LEFT; + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == 0) + ad_start = panel_widget_get_applet_at_start (toplevel->priv->panel_widget); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == 0) + ad_end = panel_widget_get_applet_at_end (toplevel->priv->panel_widget); + break; + case PANEL_ORIENTATION_RIGHT: + flags_start = PANEL_STRETCH_TOP | PANEL_STRETCH_RIGHT; + flags_end = PANEL_STRETCH_BOTTOM | PANEL_STRETCH_RIGHT; + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == (monitor_width - width)) + ad_start = panel_widget_get_applet_at_start (toplevel->priv->panel_widget); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == (monitor_width - width)) + ad_end = panel_widget_get_applet_at_end (toplevel->priv->panel_widget); + break; + case PANEL_ORIENTATION_TOP: + flags_start = PANEL_STRETCH_TOP | PANEL_STRETCH_LEFT; + flags_end = PANEL_STRETCH_TOP | PANEL_STRETCH_RIGHT; + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == 0) + ad_start = panel_widget_get_applet_at_start (toplevel->priv->panel_widget); + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == (monitor_width - width)) + ad_end = panel_widget_get_applet_at_end (toplevel->priv->panel_widget); + break; + case PANEL_ORIENTATION_BOTTOM: + flags_start = PANEL_STRETCH_BOTTOM | PANEL_STRETCH_LEFT; + flags_end = PANEL_STRETCH_BOTTOM | PANEL_STRETCH_RIGHT; + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == 0) + ad_start = panel_widget_get_applet_at_start (toplevel->priv->panel_widget); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == (monitor_width - width)) + ad_end = panel_widget_get_applet_at_end (toplevel->priv->panel_widget); + break; + } + } + if (ad_start) + widget_start = ad_start->applet; + if (ad_end) + widget_end = ad_end->applet; + if (widget_start != toplevel->priv->extended_widget_at_start || + flags_start != toplevel->priv->extended_flags_at_start) { + cancel_extension (toplevel, TRUE); + toplevel->priv->extended_widget_at_start = widget_start; + toplevel->priv->extended_flags_at_start = flags_start; + create_extension (toplevel, TRUE); + } + if (widget_end != toplevel->priv->extended_widget_at_end || + flags_end != toplevel->priv->extended_flags_at_end) { + cancel_extension (toplevel, FALSE); + toplevel->priv->extended_widget_at_end = widget_end; + toplevel->priv->extended_flags_at_end = flags_end; + create_extension (toplevel, FALSE); + } +} + +static void +panel_toplevel_update_corners (PanelToplevel *toplevel) +{ + int monitor_width, monitor_height; + int width, height; + + panel_toplevel_get_monitor_geometry ( + toplevel, NULL, NULL, &monitor_width, &monitor_height); + + width = toplevel->priv->geometry.width; + height = toplevel->priv->geometry.height; + + if (toplevel->priv->buttons_enabled || + toplevel->priv->auto_hide || + ! toplevel->priv->expand) { + gtk_widget_hide (toplevel->priv->corner_top_left_vertical); + gtk_widget_hide (toplevel->priv->corner_top_right_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_right_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_left_vertical); + gtk_widget_hide (toplevel->priv->corner_top_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_top_right_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_right_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_left_horizontal); + } else { + switch (toplevel->priv->orientation) { + case PANEL_ORIENTATION_LEFT: + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == 0) + gtk_widget_show (toplevel->priv->corner_top_left_vertical); + else + gtk_widget_hide (toplevel->priv->corner_top_left_vertical); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == 0) + gtk_widget_show (toplevel->priv->corner_bottom_left_vertical); + else + gtk_widget_hide (toplevel->priv->corner_bottom_left_vertical); + gtk_widget_hide (toplevel->priv->corner_top_right_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_right_vertical); + gtk_widget_hide (toplevel->priv->corner_top_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_top_right_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_right_horizontal); + break; + case PANEL_ORIENTATION_RIGHT: + gtk_widget_hide (toplevel->priv->corner_top_left_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_left_vertical); + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == (monitor_width - width)) + gtk_widget_show (toplevel->priv->corner_top_right_vertical); + else + gtk_widget_hide (toplevel->priv->corner_top_right_vertical); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == (monitor_width - width)) + gtk_widget_show (toplevel->priv->corner_bottom_right_vertical); + else + gtk_widget_hide (toplevel->priv->corner_bottom_right_vertical); + gtk_widget_hide (toplevel->priv->corner_top_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_top_right_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_right_horizontal); + break; + case PANEL_ORIENTATION_TOP: + gtk_widget_hide (toplevel->priv->corner_top_left_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_left_vertical); + gtk_widget_hide (toplevel->priv->corner_top_right_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_right_vertical); + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == 0) + gtk_widget_show (toplevel->priv->corner_top_left_horizontal); + else + gtk_widget_hide (toplevel->priv->corner_top_left_horizontal); + if (toplevel->priv->geometry.y == 0 && toplevel->priv->geometry.x == (monitor_width - width)) + gtk_widget_show (toplevel->priv->corner_top_right_horizontal); + else + gtk_widget_hide (toplevel->priv->corner_top_right_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_bottom_right_horizontal); + break; + case PANEL_ORIENTATION_BOTTOM: + gtk_widget_hide (toplevel->priv->corner_top_left_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_left_vertical); + gtk_widget_hide (toplevel->priv->corner_top_right_vertical); + gtk_widget_hide (toplevel->priv->corner_bottom_right_vertical); + gtk_widget_hide (toplevel->priv->corner_top_left_horizontal); + gtk_widget_hide (toplevel->priv->corner_top_right_horizontal); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == 0) + gtk_widget_show (toplevel->priv->corner_bottom_left_horizontal); + else + gtk_widget_hide (toplevel->priv->corner_bottom_left_horizontal); + if (toplevel->priv->geometry.y == (monitor_height - height) && toplevel->priv->geometry.x == (monitor_width - width)) + gtk_widget_show (toplevel->priv->corner_bottom_right_horizontal); + else + gtk_widget_hide (toplevel->priv->corner_bottom_right_horizontal); + break; + } + } + + panel_toplevel_update_extends(toplevel); +} + +static void panel_toplevel_update_hide_buttons (PanelToplevel *toplevel) { if (toplevel->priv->buttons_enabled) @@ -2049,6 +2381,7 @@ panel_toplevel_update_position (PanelTop } panel_toplevel_update_edges (toplevel); + panel_toplevel_update_corners (toplevel); panel_toplevel_update_description (toplevel); } @@ -2375,6 +2708,7 @@ panel_toplevel_attach_to_widget (PanelTo panel_toplevel_set_expand (toplevel, FALSE); panel_toplevel_update_attach_orientation (toplevel); panel_toplevel_update_hide_buttons (toplevel); + panel_toplevel_update_corners (toplevel); gtk_widget_queue_resize (GTK_WIDGET (toplevel)); } @@ -3101,6 +3435,7 @@ panel_toplevel_hide (PanelToplevel *t } panel_toplevel_update_hide_buttons (toplevel); + panel_toplevel_update_corners (toplevel); } if (toplevel->priv->animate && GTK_WIDGET_REALIZED (toplevel)) @@ -3143,6 +3478,7 @@ panel_toplevel_unhide (PanelToplevel *to toplevel->priv->state = PANEL_STATE_NORMAL; panel_toplevel_update_hide_buttons (toplevel); + panel_toplevel_update_corners (toplevel); if (toplevel->priv->attach_toplevel) panel_toplevel_push_autohide_disabler (toplevel->priv->attach_toplevel); @@ -3886,19 +4222,43 @@ panel_toplevel_setup_widgets (PanelTople { GtkWidget *container; - toplevel->priv->table = gtk_table_new (3, 3, FALSE); + toplevel->priv->table = gtk_table_new (5, 5, FALSE); toplevel->priv->hide_button_top = - panel_toplevel_add_hide_button (toplevel, GTK_ARROW_UP, 1, 2, 0, 1); + panel_toplevel_add_hide_button (toplevel, GTK_ARROW_UP, 2, 3, 0, 1); toplevel->priv->hide_button_bottom = - panel_toplevel_add_hide_button (toplevel, GTK_ARROW_DOWN, 1, 2, 2, 3); + panel_toplevel_add_hide_button (toplevel, GTK_ARROW_DOWN, 2, 3, 4, 5); toplevel->priv->hide_button_left = - panel_toplevel_add_hide_button (toplevel, GTK_ARROW_LEFT, 0, 1, 1, 2); + panel_toplevel_add_hide_button (toplevel, GTK_ARROW_LEFT, 0, 1, 2, 3); toplevel->priv->hide_button_right = - panel_toplevel_add_hide_button (toplevel, GTK_ARROW_RIGHT, 2, 3, 1, 2); + panel_toplevel_add_hide_button (toplevel, GTK_ARROW_RIGHT, 4, 5, 2, 3); + + toplevel->priv->corner_top_left_horizontal = + panel_toplevel_add_rounded_corner (toplevel, 0, 1, 1, 2); + + toplevel->priv->corner_top_right_horizontal = + panel_toplevel_add_rounded_corner (toplevel, 4, 5, 1, 2); + + toplevel->priv->corner_bottom_left_horizontal = + panel_toplevel_add_rounded_corner (toplevel, 0, 1, 3, 4); + + toplevel->priv->corner_bottom_right_horizontal = + panel_toplevel_add_rounded_corner (toplevel, 4, 5, 3, 4); + + toplevel->priv->corner_top_left_vertical = + panel_toplevel_add_rounded_corner (toplevel, 1, 2, 0, 1); + + toplevel->priv->corner_bottom_left_vertical = + panel_toplevel_add_rounded_corner (toplevel, 1, 2, 4, 5); + + toplevel->priv->corner_top_right_vertical = + panel_toplevel_add_rounded_corner (toplevel, 3, 4, 0, 1); + + toplevel->priv->corner_bottom_right_vertical = + panel_toplevel_add_rounded_corner (toplevel, 3, 4, 4, 5); if (toplevel->priv->orientation & PANEL_HORIZONTAL_MASK) { gtk_widget_show (toplevel->priv->hide_button_left); @@ -3912,8 +4272,8 @@ panel_toplevel_setup_widgets (PanelTople gtk_table_attach (GTK_TABLE (toplevel->priv->table), GTK_WIDGET (toplevel->priv->inner_frame), - 1, 2, - 1, 2, + 1, 4, + 1, 4, GTK_FILL | GTK_EXPAND | GTK_SHRINK, GTK_FILL | GTK_EXPAND | GTK_SHRINK, 0, 0); @@ -4139,6 +4499,8 @@ panel_toplevel_set_expand (PanelToplevel panel_toplevel_set_y (toplevel, 0, TRUE); } + panel_toplevel_update_corners (toplevel); + gtk_widget_queue_resize (GTK_WIDGET (toplevel)); panel_widget_set_packed (toplevel->priv->panel_widget, !toplevel->priv->expand); @@ -4207,6 +4569,7 @@ panel_toplevel_set_orientation (PanelTop toplevel->priv->orientation = orientation; panel_toplevel_update_hide_buttons (toplevel); + panel_toplevel_update_corners (toplevel); panel_widget_set_orientation ( toplevel->priv->panel_widget, @@ -4411,6 +4774,8 @@ panel_toplevel_set_auto_hide (PanelTople toplevel->priv->auto_hide = auto_hide; + panel_toplevel_update_corners (toplevel); + if (toplevel->priv->auto_hide) panel_toplevel_queue_auto_hide (toplevel); else @@ -4532,6 +4897,7 @@ panel_toplevel_set_enable_buttons (Panel toplevel->priv->buttons_enabled = enable_buttons; panel_toplevel_update_hide_buttons (toplevel); + panel_toplevel_update_corners (toplevel); g_object_notify (G_OBJECT (toplevel), "buttons-enabled"); } Index: gnome-panel/panel-util.c =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-util.c,v retrieving revision 1.139 diff -u -p -r1.139 panel-util.c --- gnome-panel/panel-util.c 6 Nov 2003 12:00:55 -0000 1.139 +++ gnome-panel/panel-util.c 13 Nov 2003 20:42:16 -0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * GNOME panel utils * (C) 1997, 1998, 1999, 2000 The Free Software Foundation @@ -588,6 +589,288 @@ panel_pixmap_discovery (const char *name FALSE /* only_if_exists */, NULL /* ret_locations */); return pixmap; +} + +typedef struct { + int realize_id; + int unrealize_id; + int size_allocate_id; + int map_id; + int unmap_id; + int hierarchy_changed_id; + PanelStretchFlags flags; + GtkWidget *toplevel; +} PanelStretchInfo; + +static void +stretch_widget_calc_geometry (GtkWidget *widget, + int *x, + int *y, + int *w, + int *h) +{ + PanelStretchInfo *info; + + g_assert (x && y && w && h); + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + info->toplevel = gtk_widget_get_toplevel (widget); + + if (!(info->toplevel && GTK_WIDGET_REALIZED (info->toplevel))) + return; + + gtk_widget_translate_coordinates (widget, info->toplevel, 0, 0, x, y); + + *w = widget->allocation.width; + *h = widget->allocation.height; + + if (info->flags & PANEL_STRETCH_TOP) { + *h += *y; + *y = 0; + } + + if (info->flags & PANEL_STRETCH_LEFT) { + *w += *x; + *x = 0; + } + + if (info->flags & PANEL_STRETCH_BOTTOM) + *h = info->toplevel->allocation.height - *y; + + if (info->flags & PANEL_STRETCH_RIGHT) + *w = info->toplevel->allocation.width - *x; +} + +static void +stretch_widget_realize (GtkWidget *widget) +{ + GdkWindowAttr attributes = { 0 }; + int attributes_mask; + int x, y, w, h; + GdkWindow *eventwin; + PanelStretchInfo *info; + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + + eventwin = g_object_get_data (G_OBJECT (widget), "StretchEventWindow"); + if (eventwin != NULL) { + gdk_window_set_user_data (eventwin, NULL); + g_object_set_data (G_OBJECT (widget), "StretchEventWindow", NULL); + gdk_window_destroy (eventwin); + } + + stretch_widget_calc_geometry (widget, &x, &y, &w, &h); + if (!(info->toplevel && GTK_WIDGET_REALIZED (info->toplevel))) + return; + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = x; + attributes.y = y; + attributes.width = w; + attributes.height = h; + attributes.wclass = GDK_INPUT_ONLY; + attributes.event_mask = (GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_KEY_PRESS_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK); + attributes_mask = GDK_WA_X | GDK_WA_Y; + + eventwin = gdk_window_new (info->toplevel->window, + &attributes, + attributes_mask); + gdk_window_set_user_data (eventwin, widget); + + g_object_set_data (G_OBJECT (widget), + "StretchEventWindow", + eventwin); +} + +static void +stretch_widget_unrealize (GtkWidget *widget) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (widget), + "StretchEventWindow"); + if (eventwin == NULL) + return; + + gdk_window_set_user_data (eventwin, NULL); + gdk_window_destroy (eventwin); + g_object_set_data (G_OBJECT (widget), + "StretchEventWindow", + NULL); +} + +/* Evil but otherwise it doesn't seem + * to work. There needs to be a cleaner + * solution */ +static gboolean +lower_in_idle (gpointer data) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (data), + "StretchEventWindow"); + + g_object_unref (G_OBJECT (data)); + + if (eventwin == NULL) + return FALSE; + + gdk_window_lower (eventwin); + return FALSE; +} + + +static void +stretch_widget_map (GtkWidget *widget) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (widget), + "StretchEventWindow"); + if (eventwin == NULL) + return; + + if (GTK_WIDGET_MAPPED (widget)) { + gdk_window_show (eventwin); + gdk_window_lower (eventwin); + g_idle_add (lower_in_idle, + g_object_ref (G_OBJECT (widget))); + } +} + +static void +stretch_widget_unmap (GtkWidget *widget) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (widget), + "StretchEventWindow"); + if (eventwin == NULL) + return; + + gdk_window_hide (eventwin); +} + + +static void +stretch_widget_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GdkWindow *eventwin; + int x, y, w, h; + int old_x, old_y, old_w, old_h, old_d; + PanelStretchInfo *info; + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + + eventwin = g_object_get_data (G_OBJECT (widget), "StretchEventWindow"); + if (!eventwin) + return; + + stretch_widget_calc_geometry (widget, &x, &y, &w, &h); + if (!(info->toplevel && GTK_WIDGET_REALIZED (info->toplevel))) + return; + + gdk_window_get_geometry (eventwin, &old_x, &old_y, &old_w, &old_h, &old_d); + + if ((x == old_x) && (y == old_y) && (w == old_w) && (h == old_h)) + return; + + /* somewhat evil */ + stretch_widget_unrealize (widget); + stretch_widget_realize (widget); + stretch_widget_map (widget); +} + +static void +stretch_widget_hierarchy_changed (GtkWidget *widget, + GtkWidget *previous_toplevel) +{ + stretch_widget_unrealize (widget); + stretch_widget_realize (widget); + stretch_widget_map (widget); +} + +static void +stretch_cancel (GtkWidget *widget) +{ + PanelStretchInfo *info; + + info = g_object_get_data (G_OBJECT (widget), "stretch-info"); + + if (info) { + stretch_widget_unrealize (widget); + + g_signal_handler_disconnect (widget, info->realize_id); + g_signal_handler_disconnect (widget, info->unrealize_id); + g_signal_handler_disconnect (widget, info->size_allocate_id); + g_signal_handler_disconnect (widget, info->map_id); + g_signal_handler_disconnect (widget, info->unmap_id); + g_signal_handler_disconnect (widget, info->hierarchy_changed_id); + + g_object_set_data (G_OBJECT (widget), "stretch-info", NULL); + } +} + +void +panel_stretch_events_to_toplevel (GtkWidget *widget, + PanelStretchFlags flags) +{ + PanelStretchInfo *info; + + if (flags == PANEL_STRETCH_NONE) { + stretch_cancel (widget); + return; + } + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + + if (info) { + if (info->flags == flags && + GTK_WIDGET_REALIZED (widget) && + info->toplevel == gtk_widget_get_toplevel (widget)) + return; + info->flags = flags; + stretch_widget_unrealize (widget); + stretch_widget_realize (widget); + stretch_widget_map (widget); + return; + } + + info = g_new0 (PanelStretchInfo, 1); + + info->realize_id = + g_signal_connect_after (GTK_WIDGET (widget), "realize", + G_CALLBACK (stretch_widget_realize), + NULL); + info->unrealize_id = + g_signal_connect (GTK_WIDGET (widget), "unrealize", + G_CALLBACK (stretch_widget_unrealize), + NULL); + info->size_allocate_id = + g_signal_connect_after (GTK_WIDGET (widget), "size_allocate", + G_CALLBACK (stretch_widget_size_allocate), + NULL); + info->map_id = + g_signal_connect_after (GTK_WIDGET (widget), "map", + G_CALLBACK (stretch_widget_map), + NULL); + info->unmap_id = + g_signal_connect_after (GTK_WIDGET (widget), "unmap", + G_CALLBACK (stretch_widget_unmap), + NULL); + info->hierarchy_changed_id = + g_signal_connect_after (GTK_WIDGET (widget), "hierarchy_changed", + G_CALLBACK (stretch_widget_hierarchy_changed), + NULL); + + info->flags = flags; + + g_object_set_data_full (G_OBJECT (widget), "stretch-info", info, g_free); + + if (GTK_WIDGET_REALIZED (widget)) + stretch_widget_realize (widget); + if (GTK_WIDGET_MAPPED (widget)) + stretch_widget_map (widget); + } /* stolen from gtk */ Index: gnome-panel/panel-util.h =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-util.h,v retrieving revision 1.76 diff -u -p -r1.76 panel-util.h --- gnome-panel/panel-util.h 6 Nov 2003 12:00:55 -0000 1.76 +++ gnome-panel/panel-util.h 13 Nov 2003 20:42:16 -0000 @@ -11,6 +11,14 @@ G_BEGIN_DECLS +typedef enum { + PANEL_STRETCH_NONE = 0, + PANEL_STRETCH_TOP = 1 << 0, + PANEL_STRETCH_RIGHT = 1 << 1, + PANEL_STRETCH_BOTTOM = 1 << 2, + PANEL_STRETCH_LEFT = 1 << 3, +} PanelStretchFlags; + typedef void (*UpdateFunction) (gpointer); /* TRUE if string is NULL or the first character is '\0' */ @@ -76,6 +84,9 @@ gboolean panel_is_program_in_path (const char * panel_pixmap_discovery (const char *name, gboolean fallback); + +void panel_stretch_events_to_toplevel (GtkWidget *widget, + PanelStretchFlags flags); void panel_signal_connect_object_while_alive (gpointer object, const gchar *signal, Index: gnome-panel/panel-widget.c =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-widget.c,v retrieving revision 1.367 diff -u -p -r1.367 panel-widget.c --- gnome-panel/panel-widget.c 3 Nov 2003 16:22:45 -0000 1.367 +++ gnome-panel/panel-widget.c 13 Nov 2003 20:42:16 -0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* Gnome panel: panel widget * (C) 1997,1998,1999,2000 the Free Software Foundation * (C) 2000 Eazel, Inc. @@ -2931,4 +2932,39 @@ panel_widget_register_open_dialog (Panel panel_signal_connect_object_while_alive (dialog, "destroy", G_CALLBACK (panel_widget_open_dialog_destroyed), panel); +} + +AppletData * +panel_widget_get_applet_at_start (PanelWidget *panel) +{ + GList *l; + AppletData *ad; + + g_return_val_if_fail (PANEL_IS_WIDGET (panel), NULL); + + l = panel->applet_list; + if (l) { + ad = l->data; + if (ad->constrained <= 1) + return ad; + } + return NULL; +} + +AppletData * +panel_widget_get_applet_at_end (PanelWidget *panel) +{ + GList *l; + AppletData *ad; + + g_return_val_if_fail (PANEL_IS_WIDGET (panel), NULL); + + l = g_list_last (panel->applet_list); + if (l) { + ad = l->data; + if (ad->constrained + ad->cells >= panel->size - 1) + return ad; + } + + return NULL; } Index: gnome-panel/panel-widget.h =================================================================== RCS file: /cvs/gnome/gnome-panel/gnome-panel/panel-widget.h,v retrieving revision 1.158 diff -u -p -r1.158 panel-widget.h --- gnome-panel/panel-widget.h 3 Nov 2003 16:22:45 -0000 1.158 +++ gnome-panel/panel-widget.h 13 Nov 2003 20:42:16 -0000 @@ -207,6 +207,8 @@ gboolean panel_widget_get_applet_locked GtkWidget *applet); gboolean panel_widget_toggle_applet_locked (PanelWidget *panel, GtkWidget *applet); +AppletData *panel_widget_get_applet_at_start (PanelWidget *panel); +AppletData *panel_widget_get_applet_at_end (PanelWidget *panel); void panel_widget_register_open_dialog (PanelWidget *panel, GtkWidget *dialog); Index: icons/Makefile.am =================================================================== RCS file: /cvs/gnome/gnome-panel/icons/Makefile.am,v retrieving revision 1.5 diff -u -p -r1.5 Makefile.am --- icons/Makefile.am 17 Jul 2003 11:18:39 -0000 1.5 +++ icons/Makefile.am 13 Nov 2003 20:42:16 -0000 @@ -18,6 +18,10 @@ icon_DATA = \ gnome-run.png \ gnome-screenshot.png \ panel-drawer.png \ + panel-corner-bottom-left.png \ + panel-corner-bottom-right.png \ + panel-corner-top-left.png \ + panel-corner-top-right.png \ gnome-main-menu.png \ $(NULL) Index: libpanel-applet/panel-applet.c =================================================================== RCS file: /cvs/gnome/gnome-panel/libpanel-applet/panel-applet.c,v retrieving revision 1.84 diff -u -p -r1.84 panel-applet.c --- libpanel-applet/panel-applet.c 13 Nov 2003 12:35:26 -0000 1.84 +++ libpanel-applet/panel-applet.c 13 Nov 2003 20:42:16 -0000 @@ -1,3 +1,4 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* * panel-applet.c: panel applet writing library. * @@ -52,6 +53,14 @@ #include "panel-applet-marshal.h" #include "panel-applet-enums.h" +typedef enum { + PANEL_STRETCH_NONE = 0, + PANEL_STRETCH_TOP = 1 << 0, + PANEL_STRETCH_RIGHT = 1 << 1, + PANEL_STRETCH_BOTTOM = 1 << 2, + PANEL_STRETCH_LEFT = 1 << 3, +} PanelStretchFlags; + #define PANEL_APPLET_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), PANEL_TYPE_APPLET, PanelAppletPrivate)) struct _PanelAppletPrivate { @@ -78,6 +87,10 @@ struct _PanelAppletPrivate { guint hierarchy_changed_id; gboolean locked_down; + + GtkWidget *stretch_widget; + GdkWindow *toplevel_window; + PanelStretchFlags stretch_flags; }; static GObjectClass *parent_class; @@ -99,6 +112,8 @@ static guint panel_applet_signals [LAST_ #define PROPERTY_FLAGS "panel-applet-flags" #define PROPERTY_SIZE_HINTS "panel-applet-size-hints" #define PROPERTY_LOCKED_DOWN "panel-applet-locked-down" +#define PROPERTY_TOPLEVEL_WINDOW "panel-applet-toplevel-window" +#define PROPERTY_STRETCH_FLAGS "panel-applet-stretch-flags" enum { PROPERTY_ORIENT_IDX, @@ -107,6 +122,8 @@ enum { PROPERTY_FLAGS_IDX, PROPERTY_SIZE_HINTS_IDX, PROPERTY_LOCKED_DOWN_IDX, + PROPERTY_TOPLEVEL_WINDOW_IDX, + PROPERTY_STRETCH_FLAGS_IDX, }; static void @@ -369,6 +386,339 @@ panel_applet_get_popup_component (PanelA return bonobo_control_get_popup_ui_component (applet->priv->control); } +typedef struct { + int realize_id; + int unrealize_id; + int size_allocate_id; + int map_id; + int unmap_id; + int hierarchy_changed_id; + PanelStretchFlags flags; + GdkWindow *toplevel_window; +} PanelStretchInfo; + +static gboolean +gdk_window_translate_coordinates (GdkWindow *src_window, + GdkWindow *dest_window, + int src_x, + int src_y, + int *dest_x, + int *dest_y) +{ + int dx, dy; + + if (gdk_drawable_get_screen (src_window) != gdk_drawable_get_screen (dest_window)) + return FALSE; + + gdk_window_get_origin (src_window, &dx, &dy); + src_x += dx; + src_y += dy; + gdk_window_get_origin (dest_window, &dx, &dy); + src_x -= dx; + src_y -= dy; + + if (dest_x) + *dest_x = src_x; + if (dest_y) + *dest_y = src_y; + return TRUE; +} + +static void +stretch_widget_calc_geometry (GtkWidget *widget, + int *x, + int *y, + int *w, + int *h) +{ + PanelStretchInfo *info; + + g_assert (x && y && w && h); + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + + gdk_window_translate_coordinates (widget->window, info->toplevel_window, 0, 0, x, y); + + *w = widget->allocation.width; + *h = widget->allocation.height; + + if (info->flags & PANEL_STRETCH_TOP) { + *h += *y; + *y = 0; + } + + if (info->flags & PANEL_STRETCH_LEFT) { + *w += *x; + *x = 0; + } + + if (info->flags & (PANEL_STRETCH_BOTTOM | PANEL_STRETCH_RIGHT)) { + int toplevel_width, toplevel_height; + + gdk_window_get_geometry (info->toplevel_window, NULL, NULL, &toplevel_width, &toplevel_height, NULL); + + if (info->flags & PANEL_STRETCH_BOTTOM) + *h = toplevel_height - *y; + + if (info->flags & PANEL_STRETCH_RIGHT) + *w = toplevel_width - *x; + } +} + +static void +stretch_widget_realize (GtkWidget *widget) +{ + GdkWindowAttr attributes = { 0 }; + int attributes_mask; + int x, y, w, h; + GdkWindow *eventwin; + PanelStretchInfo *info; + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + + eventwin = g_object_get_data (G_OBJECT (widget), "StretchEventWindow"); + if (eventwin != NULL) { + gdk_window_set_user_data (eventwin, NULL); + g_object_set_data (G_OBJECT (widget), "StretchEventWindow", NULL); + gdk_window_destroy (eventwin); + } + + stretch_widget_calc_geometry (widget, &x, &y, &w, &h); + + attributes.window_type = GDK_WINDOW_CHILD; + attributes.x = x; + attributes.y = y; + attributes.width = w; + attributes.height = h; + attributes.wclass = GDK_INPUT_ONLY; + attributes.event_mask = (GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_KEY_PRESS_MASK | + GDK_ENTER_NOTIFY_MASK | + GDK_LEAVE_NOTIFY_MASK); + attributes_mask = GDK_WA_X | GDK_WA_Y; + + eventwin = gdk_window_new (info->toplevel_window, + &attributes, + attributes_mask); + gdk_window_set_user_data (eventwin, widget); + + g_object_set_data (G_OBJECT (widget), + "StretchEventWindow", + eventwin); +} + +static void +stretch_widget_unrealize (GtkWidget *widget) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (widget), + "StretchEventWindow"); + if (eventwin == NULL) + return; + + gdk_window_set_user_data (eventwin, NULL); + gdk_window_destroy (eventwin); + g_object_set_data (G_OBJECT (widget), + "StretchEventWindow", + NULL); +} + +/* Evil but otherwise it doesn't seem + * to work. There needs to be a cleaner + * solution */ +static gboolean +lower_in_idle (gpointer data) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (data), + "StretchEventWindow"); + + g_object_unref (G_OBJECT (data)); + + if (eventwin == NULL) + return FALSE; + + gdk_window_lower (eventwin); + return FALSE; +} + + +static void +stretch_widget_map (GtkWidget *widget) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (widget), + "StretchEventWindow"); + if (eventwin == NULL) + return; + + if (GTK_WIDGET_MAPPED (widget)) { + gdk_window_show (eventwin); + gdk_window_lower (eventwin); + g_idle_add (lower_in_idle, + g_object_ref (G_OBJECT (widget))); + } +} + +static void +stretch_widget_unmap (GtkWidget *widget) +{ + GdkWindow *eventwin = g_object_get_data (G_OBJECT (widget), + "StretchEventWindow"); + if (eventwin == NULL) + return; + + gdk_window_hide (eventwin); +} + + +static void +stretch_widget_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GdkWindow *eventwin; + int x, y, w, h; + int old_x, old_y, old_w, old_h, old_d; + + eventwin = g_object_get_data (G_OBJECT (widget), "StretchEventWindow"); + if (!eventwin) + return; + + stretch_widget_calc_geometry (widget, &x, &y, &w, &h); + + gdk_window_get_geometry (eventwin, &old_x, &old_y, &old_w, &old_h, &old_d); + + if ((x == old_x) && (y == old_y) && (w == old_w) && (h == old_h)) + return; + + /* somewhat evil */ + stretch_widget_unrealize (widget); + stretch_widget_realize (widget); + stretch_widget_map (widget); +} + +static void +stretch_widget_hierarchy_changed (GtkWidget *widget, + GtkWidget *previous_toplevel) +{ + stretch_widget_unrealize (widget); + stretch_widget_realize (widget); + stretch_widget_map (widget); +} + +static void +stretch_cancel (GtkWidget *widget) +{ + PanelStretchInfo *info; + + info = g_object_get_data (G_OBJECT (widget), "stretch-info"); + + if (info) { + stretch_widget_unrealize (widget); + + g_signal_handler_disconnect (widget, info->realize_id); + g_signal_handler_disconnect (widget, info->unrealize_id); + g_signal_handler_disconnect (widget, info->size_allocate_id); + g_signal_handler_disconnect (widget, info->map_id); + g_signal_handler_disconnect (widget, info->unmap_id); + g_signal_handler_disconnect (widget, info->hierarchy_changed_id); + + g_object_set_data (G_OBJECT (widget), "stretch-info", NULL); + } +} + +static void +panel_stretch_events_to_toplevel_window (GtkWidget *widget, + GdkWindow *toplevel_window, + PanelStretchFlags flags) +{ + PanelStretchInfo *info; + + if (flags == PANEL_STRETCH_NONE) { + stretch_cancel (widget); + return; + } + + info = g_object_get_data (G_OBJECT (widget) , "stretch-info"); + + if (info) { + if (info->flags == flags && + info->toplevel_window == toplevel_window) + return; + info->flags = flags; + info->toplevel_window = toplevel_window; + stretch_widget_unrealize (widget); + stretch_widget_realize (widget); + stretch_widget_map (widget); + return; + } + + info = g_new0 (PanelStretchInfo, 1); + + info->realize_id = + g_signal_connect_after (GTK_WIDGET (widget), "realize", + G_CALLBACK (stretch_widget_realize), + NULL); + info->unrealize_id = + g_signal_connect (GTK_WIDGET (widget), "unrealize", + G_CALLBACK (stretch_widget_unrealize), + NULL); + info->size_allocate_id = + g_signal_connect_after (GTK_WIDGET (widget), "size_allocate", + G_CALLBACK (stretch_widget_size_allocate), + NULL); + info->map_id = + g_signal_connect_after (GTK_WIDGET (widget), "map", + G_CALLBACK (stretch_widget_map), + NULL); + info->unmap_id = + g_signal_connect_after (GTK_WIDGET (widget), "unmap", + G_CALLBACK (stretch_widget_unmap), + NULL); + info->hierarchy_changed_id = + g_signal_connect_after (GTK_WIDGET (widget), "hierarchy_changed", + G_CALLBACK (stretch_widget_hierarchy_changed), + NULL); + + info->flags = flags; + info->toplevel_window = toplevel_window; + + g_object_set_data_full (G_OBJECT (widget), "stretch-info", info, g_free); + + if (GTK_WIDGET_REALIZED (widget)) + stretch_widget_realize (widget); + if (GTK_WIDGET_MAPPED (widget)) + stretch_widget_map (widget); + +} + +static void +stretch_weak_ref (gpointer data, GObject *where_object_was) +{ + PanelApplet *applet = data; + applet->priv->stretch_widget = NULL; +} + +void +panel_applet_set_stretch_widget (PanelApplet *applet, + GtkWidget *widget) +{ + if (widget != applet->priv->stretch_widget) { + if (applet->priv->stretch_widget && applet->priv->toplevel_window) { + panel_stretch_events_to_toplevel_window (applet->priv->stretch_widget, applet->priv->toplevel_window, PANEL_STRETCH_NONE); + } + if (applet->priv->stretch_widget) + g_object_weak_unref (G_OBJECT (applet->priv->stretch_widget), stretch_weak_ref, applet); + applet->priv->stretch_widget = widget; + if (applet->priv->stretch_widget) + g_object_weak_ref (G_OBJECT (applet->priv->stretch_widget), stretch_weak_ref, applet); + if (applet->priv->stretch_widget && applet->priv->toplevel_window) { + panel_stretch_events_to_toplevel_window (applet->priv->stretch_widget, applet->priv->toplevel_window, applet->priv->stretch_flags); + } + } +} + + static void panel_applet_finalize (GObject *object) { @@ -378,6 +728,9 @@ panel_applet_finalize (GObject *object) bonobo_object_unref ( BONOBO_OBJECT (applet->priv->prop_sack)); + if (applet->priv->stretch_widget) + g_object_weak_unref (G_OBJECT (applet->priv->stretch_widget), stretch_weak_ref, applet); + g_free (applet->priv->size_hints); g_free (applet->priv->prefs_key); g_free (applet->priv->background); @@ -936,6 +1289,12 @@ panel_applet_get_prop (BonoboPropertyBag case PROPERTY_LOCKED_DOWN_IDX: BONOBO_ARG_SET_BOOLEAN (arg, applet->priv->locked_down); break; + case PROPERTY_TOPLEVEL_WINDOW_IDX: + BONOBO_ARG_SET_LONG (arg, gdk_x11_drawable_get_xid (applet->priv->toplevel_window)); + break; + case PROPERTY_STRETCH_FLAGS_IDX: + BONOBO_ARG_SET_SHORT (arg, applet->priv->stretch_flags); + break; default: g_assert_not_reached (); break; @@ -1039,6 +1398,34 @@ panel_applet_set_prop (BonoboPropertyBag case PROPERTY_LOCKED_DOWN_IDX: applet->priv->locked_down = BONOBO_ARG_GET_BOOLEAN (arg); break; + case PROPERTY_TOPLEVEL_WINDOW_IDX: + { + GdkWindow *new_window; + GdkDisplay *display; + + display = gdk_screen_get_display (gdk_drawable_get_screen(GTK_WIDGET (applet)->window)); + + new_window = gdk_window_lookup_for_display (display, BONOBO_ARG_GET_LONG (arg)); + if (new_window == NULL) { + new_window = gdk_window_foreign_new_for_display (display, BONOBO_ARG_GET_LONG (arg)); + } + + if (applet->priv->toplevel_window != new_window) { + applet->priv->toplevel_window = new_window; + if (applet->priv->stretch_widget && applet->priv->toplevel_window) { + panel_stretch_events_to_toplevel_window (applet->priv->stretch_widget, applet->priv->toplevel_window, applet->priv->stretch_flags); + } + } + } + break; + case PROPERTY_STRETCH_FLAGS_IDX: + if (applet->priv->stretch_flags != BONOBO_ARG_GET_SHORT (arg)) { + applet->priv->stretch_flags = BONOBO_ARG_GET_SHORT (arg); + if (applet->priv->stretch_widget && applet->priv->toplevel_window) { + panel_stretch_events_to_toplevel_window (applet->priv->stretch_widget, applet->priv->toplevel_window, applet->priv->stretch_flags); + } + } + break; default: g_assert_not_reached (); break; @@ -1102,6 +1489,22 @@ panel_applet_property_bag (PanelApplet * _("The Applet's containing Panel is locked down"), Bonobo_PROPERTY_READABLE | Bonobo_PROPERTY_WRITEABLE); + bonobo_property_bag_add (sack, + PROPERTY_TOPLEVEL_WINDOW, + PROPERTY_TOPLEVEL_WINDOW_IDX, + BONOBO_ARG_LONG, + NULL, + _("The XID of the toplevel window of the containing panel"), + Bonobo_PROPERTY_READABLE | Bonobo_PROPERTY_WRITEABLE); + + bonobo_property_bag_add (sack, + PROPERTY_STRETCH_FLAGS, + PROPERTY_STRETCH_FLAGS_IDX, + BONOBO_ARG_SHORT, + NULL, + _("The Applet's containing Panel is locked down"), + Bonobo_PROPERTY_READABLE | Bonobo_PROPERTY_WRITEABLE); + return sack; } @@ -1364,6 +1767,9 @@ panel_applet_instance_init (PanelApplet applet->priv->size = GNOME_Vertigo_PANEL_MEDIUM; applet->priv->moving_focus_out = FALSE; + + applet->priv->stretch_widget = GTK_WIDGET (applet); + g_object_weak_ref (G_OBJECT (applet->priv->stretch_widget), stretch_weak_ref, applet); gtk_widget_set_events (GTK_WIDGET (applet), GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK); Index: libpanel-applet/panel-applet.h =================================================================== RCS file: /cvs/gnome/gnome-panel/libpanel-applet/panel-applet.h,v retrieving revision 1.36 diff -u -p -r1.36 panel-applet.h --- libpanel-applet/panel-applet.h 15 Sep 2003 22:10:46 -0000 1.36 +++ libpanel-applet/panel-applet.h 13 Nov 2003 20:42:16 -0000 @@ -143,6 +143,9 @@ void panel_applet_setup_me const BonoboUIVerb *verb_list, gpointer user_data); +void panel_applet_set_stretch_widget (PanelApplet *applet, + GtkWidget *widget); + int panel_applet_factory_main (const gchar *iid, GType applet_type,