foobar-widget.c 33.2 KB
Newer Older
1
/* GNOME panel: foobar widget
2 3
 * Copyright 1999,2000 Helix Code, Inc.
 * Copyright 2000 Eazel, Inc.
4 5 6 7 8
 *
 * Author: Jacob Berkman
 *
 */

9
/* since BASEP_IS_WIDGET() is used throughout, it makes life easier if we
10 11 12 13
 * have a GtkWindow of our own.
 */

#include <config.h>
14
#include <unistd.h>
Michael Meeks's avatar
Michael Meeks committed
15
#include <string.h>
16
#include <time.h>
17

18
#include <libgnome/libgnome.h>
19 20 21
/* Yes, yes I know, now bugger off ... */
#define WNCK_I_KNOW_THIS_IS_UNSTABLE
#include <libwnck/libwnck.h>
22 23
#include <gconf/gconf-client.h>

24 25
#include "foobar-widget.h"

26
#include "main.h"
27 28 29 30 31 32
#include "menu.h"
#include "menu-util.h"
#include "session.h"
#include "panel-widget.h"
#include "xstuff.h"
#include "basep-widget.h"
33
#include "panel-config-global.h"
34
#include "panel-util.h"
35
#include "drawer-widget.h"
36
#include "gnome-run.h"
37
#include "multiscreen-stuff.h"
38

39
#define ICON_SIZE 20
40

41
extern GlobalConfig global_config;
42
extern GSList *panel_list;
43

44 45
extern GtkTooltips *panel_tooltips;

46 47 48 49 50 51
static void foobar_widget_class_init	(FoobarWidgetClass *klass);
static void foobar_widget_instance_init (FoobarWidget *foo);
static void foobar_widget_realize	(GtkWidget *w);
static void foobar_widget_destroy	(GtkObject *o);
static void foobar_widget_size_allocate	(GtkWidget *w,
					 GtkAllocation *alloc);
52 53 54 55
static gboolean foobar_leave_notify	(GtkWidget *widget,
					 GdkEventCrossing *event);
static gboolean foobar_enter_notify	(GtkWidget *widget,
					 GdkEventCrossing *event);
56
static void append_task_menu (FoobarWidget *foo, GtkMenuShell *menu_bar);
57
static void setup_task_menu (FoobarWidget *foo);
58

59
static GList *foobars = NULL;
60

61
static GtkWindowClass *foobar_widget_parent_class = NULL;
62

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
63
GType
64
foobar_widget_get_type (void)
65
{
66 67 68 69 70 71 72 73 74 75 76 77 78
	static GType object_type = 0;

	if (object_type == 0) {
		static const GTypeInfo object_info = {
                    sizeof (FoobarWidgetClass),
                    (GBaseInitFunc)         NULL,
                    (GBaseFinalizeFunc)     NULL,
                    (GClassInitFunc)        foobar_widget_class_init,
                    NULL,                   /* class_finalize */
                    NULL,                   /* class_data */
                    sizeof (FoobarWidget),
                    0,                      /* n_preallocs */
                    (GInstanceInitFunc)     foobar_widget_instance_init
79 80
		};

81 82
		object_type = g_type_register_static (GTK_TYPE_WINDOW, "FoobarWidget", &object_info, 0);
        	foobar_widget_parent_class = g_type_class_ref (GTK_TYPE_WINDOW);
83 84 85

	}

86
	return object_type;
87 88 89 90 91
}

static void
foobar_widget_class_init (FoobarWidgetClass *klass)
{
92
	GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
93
	GtkObjectClass *object_class = GTK_OBJECT_CLASS (klass);
94

95 96
	object_class->destroy = foobar_widget_destroy;

97
	widget_class->realize = foobar_widget_realize;
98
	widget_class->size_allocate = foobar_widget_size_allocate;
99 100
	widget_class->enter_notify_event = foobar_enter_notify;
	widget_class->leave_notify_event = foobar_leave_notify;
101 102 103 104 105 106 107 108
}

static GtkWidget *
pixmap_menu_item_new (const char *text, const char *try_file)
{
	GtkWidget *item;
	GtkWidget *label;

Martin Baulig's avatar
Martin Baulig committed
109
	item = gtk_image_menu_item_new ();
110

111
	/* FIXME: listen to this gconf client key */
112
	if (try_file != NULL && panel_menu_have_icons ()) {
Martin Baulig's avatar
Martin Baulig committed
113 114
		GtkWidget *image;
		GdkPixbuf *pixbuf;
115
		char *file;
Martin Baulig's avatar
Martin Baulig committed
116

117 118 119 120 121 122 123 124 125 126
		if (g_path_is_absolute (try_file))
			file = g_strdup (try_file);
		else
			file = panel_pixmap_discovery (try_file,
						       TRUE /* fallback */);

		pixbuf = gdk_pixbuf_new_from_file (file, NULL);
		if (pixbuf != NULL &&
		    (gdk_pixbuf_get_width (pixbuf) != ICON_SIZE ||
		     gdk_pixbuf_get_height (pixbuf) != ICON_SIZE)) {
Martin Baulig's avatar
Martin Baulig committed
127 128 129
			GdkPixbuf *scaled;

			scaled = gdk_pixbuf_scale_simple (pixbuf,
130 131
							  ICON_SIZE,
							  ICON_SIZE,
Martin Baulig's avatar
Martin Baulig committed
132 133 134 135 136 137 138
							  GDK_INTERP_BILINEAR);

			gdk_pixbuf_unref (pixbuf);

			pixbuf = scaled;
		}

139
		if (pixbuf != NULL) {
Martin Baulig's avatar
Martin Baulig committed
140
			image = gtk_image_new_from_pixbuf (pixbuf);
141
			gtk_widget_show (image);
Martin Baulig's avatar
Martin Baulig committed
142 143 144 145 146

			gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
						       image);

			gdk_pixbuf_unref (pixbuf);
147
		}
148 149 150 151 152 153 154 155 156 157 158
	}

	if (text) {
		label = gtk_label_new (text);
		gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
		gtk_container_add (GTK_CONTAINER (item), label);
	}

	return item;
}

159
static void
Martin Baulig's avatar
Martin Baulig committed
160
add_tearoff (GtkMenuShell *menu)
161 162 163
{
	GtkWidget *item;

164
	if (!panel_menu_have_tearoff ())
165 166 167 168
		return;
	
	item = gtk_tearoff_menu_item_new ();
	gtk_widget_show (item);
Martin Baulig's avatar
Martin Baulig committed
169
	gtk_menu_shell_prepend (menu, item);
170 171
}

172 173 174 175
static gboolean
foobar_leave_notify (GtkWidget *widget,
		     GdkEventCrossing *event)
{
176 177
	if (GTK_WIDGET_CLASS (foobar_widget_parent_class)->leave_notify_event)
		GTK_WIDGET_CLASS (foobar_widget_parent_class)->leave_notify_event (widget,
178 179 180 181 182 183 184 185 186
								     event);

	return FALSE;
}

static gboolean
foobar_enter_notify (GtkWidget *widget,
		     GdkEventCrossing *event)
{
187 188
	if (GTK_WIDGET_CLASS (foobar_widget_parent_class)->enter_notify_event)
		GTK_WIDGET_CLASS (foobar_widget_parent_class)->enter_notify_event (widget,
189 190 191 192 193 194 195 196
								     event);

	if (global_config.autoraise)
		gdk_window_raise (widget->window);

	return FALSE;
}

197 198 199
static void
gnomecal_client (GtkWidget *w, gpointer data)
{
200
	char *v[4] = { "gnomecal", "--view", NULL, NULL };
201
	v[2] = data;
202
	if(gnome_execute_async (g_get_home_dir (), 3, v) < 0)
203 204
		panel_error_dialog("cannot_execute_gnome_calendar",
				   _("Cannot execute the gnome calendar,\n"
205
				     "perhaps it's not installed.\n"
206
				     "It is in the gnome-pim package."));
207 208
}

209 210
static void
append_actions_menu (GtkWidget *menu_bar)
211
{
212
	GtkWidget *menu, *item;
213

214
	menu = gtk_menu_new ();
215

216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244

	add_tearoff (GTK_MENU_SHELL (menu));

	menu = gtk_menu_new ();

	item = pixmap_menu_item_new (_("Run..."), "gnome-run.png");
	gtk_tooltips_set_tip (panel_tooltips, item,
			      _("Run applications, if you know the "
				"correct command to type in"),
			      NULL);
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate",
			  G_CALLBACK (show_run_dialog), 0);
	setup_internal_applet_drag (item, "RUN:NEW");

	/* FIXME: search */
	/* FIXME: shutdown or reboot */

	if (panel_is_program_in_path  ("xscreensaver")) {
		item = pixmap_menu_item_new (_("Lock Display"), 
					       "gnome-lockscreen.png");
		gtk_tooltips_set_tip (panel_tooltips, item,
				      _("Protect your computer from "
					"unauthorized use"),
				      NULL);
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
		g_signal_connect (G_OBJECT (item), "activate",
				  G_CALLBACK (panel_lock), 0);
		setup_internal_applet_drag(item, "LOCK:NEW");
245 246
	}

247 248 249 250 251 252 253 254 255 256 257 258 259
	item = pixmap_menu_item_new (_("Log Out"), "gnome-term-night.png");
	gtk_tooltips_set_tip (panel_tooltips, item,
			      _("Quit from the GNOME desktop"),
			      NULL);
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
	g_signal_connect (G_OBJECT (item), "activate",
			  G_CALLBACK (panel_quit), 0);
	setup_internal_applet_drag (item, "LOGOUT:NEW");

	add_tearoff (GTK_MENU_SHELL (menu));

	item = gtk_menu_item_new_with_label (_("Actions"));
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
260
	gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), item);
261 262 263 264 265 266

	panel_strech_events_to_toplevel (item,
					 TRUE /* top */,
					 FALSE /* right */,
					 FALSE /* bottom */,
					 FALSE /* left */);
267 268
}

269 270 271
#if 0
/* sure we won't need this????
 * -George */
272 273
static GtkWidget *
append_folder_menu (GtkWidget *menu_bar, const char *label,
274 275 276 277
		    const char *pixmap, const char *path,
		    gboolean strech_left,
		    gboolean strech_top,
		    gboolean strech_right)
278 279 280 281
{
	GtkWidget *item, *menu;

	menu = create_fake_menu_at (path,
282 283 284 285 286
				    FALSE /* applets */,
				    FALSE /* launcher_add */,
				    label /* dir_name */,
				    NULL /* pixmap_name */,
				    FALSE /* title */);
287

288
	if (menu == NULL) {
289
		g_warning (_("menu wasn't created"));
290
		return NULL;
291 292
	}

293
	if (pixmap != NULL)
294 295 296 297
		item = pixmap_menu_item_new (label, pixmap);
	else
		item = gtk_menu_item_new_with_label (label);
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);
298
	gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), item);
299

300 301 302
	g_signal_connect (G_OBJECT (menu), "show",
			  G_CALLBACK (submenu_to_display),
			  NULL);
303

304 305 306 307 308 309 310 311
	if (strech_left || strech_top || strech_right)
		panel_strech_events_to_toplevel (item,
						 strech_top,
						 strech_right,
						 FALSE,
						 strech_left);
		

312
	return menu;
313
}
314
#endif
315 316

static void
317
append_gnomecal_item (GtkWidget *menu, const char *label, const char *flag)
318
{
319
	GtkWidget *item = gtk_image_menu_item_new_with_label (label);
Martin Baulig's avatar
Martin Baulig committed
320
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
321
	g_signal_connect (G_OBJECT (item), "activate",
322 323
			  G_CALLBACK (gnomecal_client),
			  (char *)flag);
324 325
}

326 327
static void
update_clock (FoobarWidget *foo)
328
{
329
	static int day = 0;
330 331
	struct tm *das_tm;
	time_t das_time;
332
	char hour[256];
333

334 335
	if (foo->clock_label == NULL)
		return;
336

337 338 339
	time (&das_time);
	das_tm = localtime (&das_time);

340
	if (das_tm->tm_mday != day) {
341 342 343 344 345 346 347 348
		if(strftime(hour, sizeof(hour), _("%A %B %d"), das_tm) == 0) {
			/* according to docs, if the string does not fit, the
			 * contents of tmp2 are undefined, thus just use
			 * ??? */
			strcpy(hour, "???");
		}
		hour[sizeof(hour)-1] = '\0'; /* just for sanity */

349 350
		gtk_tooltips_set_tip (panel_tooltips, foo->clock_ebox,
				      hour, NULL);
351 352 353 354

		day = das_tm->tm_mday;
	}

355
	if(strftime(hour, sizeof(hour), foo->clock_format, das_tm) == 0) {
356 357 358 359 360 361
		/* according to docs, if the string does not fit, the
		 * contents of tmp2 are undefined, thus just use
		 * ??? */
		strcpy(hour, "???");
	}
	hour[sizeof(hour)-1] = '\0'; /* just for sanity */
362

363
	gtk_label_set_text (GTK_LABEL (foo->clock_label), hour);
364 365
}

366 367
static int
timeout_cb (gpointer data)
368
{
369 370 371 372 373 374 375 376 377 378
	FoobarWidget *foo = FOOBAR_WIDGET (data);

	if (foo->clock_label == NULL) {
		foo->clock_timeout = 0;
		return FALSE;
	}

	update_clock (foo);

	return TRUE;
379 380
}

381 382 383
static void
set_fooclock_format (GtkWidget *w, char *format)
{
384
	GList *li;
385

386 387
	for (li = foobars; li != NULL; li = li->next) {
		foobar_widget_set_clock_format (FOOBAR_WIDGET (li->data),
388 389
						_(format));
	}
390 391 392
}

static void
393
append_format_item (GtkWidget *menu, const char *format)
394
{
395
	char hour[256];
396 397 398 399 400
	GtkWidget *item;
	struct tm *das_tm;
	time_t das_time = 0;

	das_tm = localtime (&das_time);
401 402 403 404 405 406 407
	if (strftime (hour, sizeof(hour), _(format), das_tm) == 0) {
		/* according to docs, if the string does not fit, the
		 * contents of tmp2 are undefined, thus just use
		 * ??? */
		strcpy(hour, "???");
	}
	hour[sizeof(hour)-1] = '\0'; /* just for sanity */
408

409
	item = gtk_image_menu_item_new_with_label (hour);
Martin Baulig's avatar
Martin Baulig committed
410
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
411 412
	g_signal_connect (G_OBJECT (item), "activate",
			  G_CALLBACK (set_fooclock_format),
413
			  (char *)format);
414 415
}

416 417 418 419 420 421
static void
set_time_cb (GtkWidget *menu_item, char *path)
{
	char *v[2] = { path };
	
	if (gnome_execute_async (g_get_home_dir (), 1, v) < 0)
422 423 424
		panel_error_dialog ("could_not_call_time_admin",
				    _("Could not call time-admin\n"
				      "Perhaps time-admin is not installed"));
425 426
}

427
static GtkWidget *
428
append_clock_menu (FoobarWidget *foo, GtkWidget *menu_bar)
429
{
430
	GtkWidget *item, *menu, *menu2;
431
	gchar *time_admin_path;
432 433 434 435 436 437 438 439
	int i;
	const char *cals[] = { 
		N_("Today"),      "dayview",
		N_("This Week"),  "weekview",
		N_("This Month"), "monthview",
		NULL
	};

440 441 442
	const char *formats[] = {
		N_("%H:%M"),
		N_("%H:%M:%S"),
443 444
		N_("%l:%M %p"),
		N_("%l:%M:%S %p"),
445 446 447
		NULL
	};

448
	menu = gtk_menu_new ();
449 450
	
#if 0 /* put back when evolution can do this */
451
	item = gtk_image_menu_item_new_with_label (_("Add appointement..."));
Martin Baulig's avatar
Martin Baulig committed
452
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
453 454 455 456

	add_menu_separator (menu);
#endif

457
	/* FIXME: wtf is time-admin???? */
458
	time_admin_path = g_find_program_in_path  ("time-admin");
459
	if (time_admin_path != NULL) {
460
		item = gtk_image_menu_item_new_with_label (_("Set Time"));
461
		g_signal_connect (G_OBJECT (item), "activate",
462 463
				  G_CALLBACK (set_time_cb),
				  time_admin_path);
Martin Baulig's avatar
Martin Baulig committed
464
		gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
465 466 467
		add_menu_separator (menu);
	}

468 469 470
	for (i=0; cals[i]; i+=2)
		append_gnomecal_item (menu, _(cals[i]), cals[i+1]);

471 472
	add_menu_separator (menu);

473
	menu2 = gtk_menu_new ();
474 475 476
	for (i=0; formats[i]; i++)
		append_format_item (menu2, formats[i]);

Martin Baulig's avatar
Martin Baulig committed
477
	add_tearoff (GTK_MENU_SHELL (menu2));
478

479
	item = gtk_image_menu_item_new_with_label (_("Format"));
480
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu2);
Martin Baulig's avatar
Martin Baulig committed
481
	gtk_menu_shell_append (GTK_MENU_SHELL (menu), item);
482

Martin Baulig's avatar
Martin Baulig committed
483
	add_tearoff (GTK_MENU_SHELL (menu));
484

485
	item = gtk_menu_item_new ();
486

487 488 489
	foo->clock_label = gtk_label_new ("");
	foo->clock_timeout = gtk_timeout_add (1000, timeout_cb, foo);

490
	foo->clock_ebox = item;
491
	gtk_container_add (GTK_CONTAINER (item), foo->clock_label);
492 493
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), menu);

494
	gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), item);
495

496 497 498 499 500 501
	panel_strech_events_to_toplevel (item,
					 TRUE /* top */,
					 FALSE /* right */,
					 FALSE /* bottom */,
					 FALSE /* left */);

502 503 504
	return item;
}

505 506 507
void
foobar_widget_global_set_clock_format (const char *format)
{
508
	GList *li;
509

510 511
	for (li = foobars; li != NULL; li = li->next) {
		foobar_widget_set_clock_format (FOOBAR_WIDGET (li->data),
512 513
						format);
	}
514 515
}

516 517 518 519 520 521
void
foobar_widget_set_clock_format (FoobarWidget *foo, const char *clock_format)
{
	g_free (foo->clock_format);
	foo->clock_format = g_strdup (clock_format);

522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
	if(foo->clock_label) {
		time_t das_time;
		struct tm *das_tm;
		char hour[256];
		gchar *str_utf8;
		int width;
		PangoLayout *layout;

		das_time = 0;
		das_tm = localtime (&das_time);
		strftime(hour, sizeof(hour), _(clock_format), das_tm);
		str_utf8 = g_locale_to_utf8((const gchar *)hour, strlen(hour), NULL, NULL, NULL);
		if(str_utf8) {
			layout = gtk_widget_create_pango_layout (foo->clock_label, str_utf8);
			pango_layout_get_pixel_size (layout, &width, NULL);
			width += 8; /* Padding */
			gtk_widget_set_size_request (foo->clock_label, width, 0);
			g_object_unref (G_OBJECT(layout));
		}
	}
542 543 544
	update_clock (foo);
}

545
void
546
foobar_widget_update_winhints (FoobarWidget *foo)
547
{
548
	GtkWidget *w = GTK_WIDGET (foo);
549

550 551
	gtk_window_set_decorated (GTK_WINDOW (w), FALSE);
	gtk_window_stick (GTK_WINDOW (w));
552

553
	xstuff_set_wmspec_dock_hints (w->window, FALSE /* autohide */);
554 555
}

556 557 558
static void
foobar_widget_realize (GtkWidget *w)
{
559 560 561
	gtk_window_set_wmclass (GTK_WINDOW (w),
				"panel_window", "Panel");

562 563
	if (GTK_WIDGET_CLASS (foobar_widget_parent_class)->realize)
		GTK_WIDGET_CLASS (foobar_widget_parent_class)->realize (w);
564

565
	foobar_widget_update_winhints (FOOBAR_WIDGET (w));
566
	xstuff_set_no_group_and_no_input (w->window);
567 568

	setup_task_menu (FOOBAR_WIDGET (w));
569 570 571 572 573 574

	xstuff_set_wmspec_strut (w->window,
				 0 /* left */,
				 0 /* right */,
				 w->allocation.height /* top */,
				 0 /* bottom */);
575 576
}

577
static void
578
programs_menu_to_display (GtkWidget *menu)
579
{
580
	if (menu_need_reread (menu)) {
581 582
		int flags;

583 584 585 586 587 588 589 590
		while (GTK_MENU_SHELL (menu)->children)
			gtk_widget_destroy (GTK_MENU_SHELL (menu)->children->data);
		flags = MAIN_MENU_SYSTEM;
		if (got_kde_menus ())
			flags |= MAIN_MENU_KDE_SUB;
		if (got_distro_menus ())
			flags |= MAIN_MENU_DISTRIBUTION_SUB;
		create_root_menu (menu, TRUE, flags, TRUE, FALSE, FALSE /* run_item */);
591 592
	}
}
593

594 595 596
static void
set_the_task_submenu (FoobarWidget *foo, GtkWidget *item)
{
597
	foo->task_menu = gtk_menu_new ();
598 599
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (item), foo->task_menu);
	/*g_message ("setting...");*/
600 601 602
	g_signal_connect (G_OBJECT (foo->task_menu), "show",
			  G_CALLBACK (our_gtk_menu_position),
			  NULL);
603 604 605
}

static void
606
focus_window (GtkWidget *w, WnckWindow *window)
607
{
608 609 610
	WnckScreen *screen = wnck_screen_get (0 /* FIXME screen number */);
	WnckWorkspace *wspace = wnck_screen_get_active_workspace (screen);

611 612
	if (wspace != NULL)
		wnck_window_move_to_workspace (window, wspace);
613 614 615 616 617
	if (wnck_window_is_minimized (window)) 
		wnck_window_unminimize (window);
	wnck_window_activate (window);
}

618
/* No need to unref, in fact do NOT unref the return */
619 620 621 622 623 624 625 626
static GdkPixbuf *
get_default_image (void)
{
	static GdkPixbuf *pixbuf = NULL;
	static gboolean looked   = FALSE;

	if (! looked) {
		GdkPixbuf *pb = NULL, *scaled = NULL;
627 628 629 630 631 632 633 634 635
		char *name = panel_pixmap_discovery ("gnome-tasklist.png", FALSE /* fallback */);
		if (name == NULL)
			/* evil fallback huh? */
			name = panel_pixmap_discovery ("apple-red.png", FALSE /* fallback */);

		if (name != NULL) {
			pb = gdk_pixbuf_new_from_file (name, NULL);
			g_free (name);
		}
636 637 638 639 640 641 642 643 644 645 646 647 648
		
		if (pb != NULL) {
			scaled = gdk_pixbuf_scale_simple (pb, 20, 20, 
							  GDK_INTERP_BILINEAR);
			gdk_pixbuf_unref (pb);

			pixbuf = scaled;
		}

		looked = TRUE;
	}

	return pixbuf;
649 650 651
}

static void
652
add_window (WnckWindow *window, FoobarWidget *foo)
653 654 655 656
{
	GtkWidget *item, *label;
	char *title = NULL;
	int slen;
Martin Baulig's avatar
Martin Baulig committed
657
	GtkWidget *image = NULL;
658 659 660 661
	GdkPixbuf *pb;
	const char *name;
	WnckScreen *screen = wnck_screen_get (0 /* FIXME screen number */);
	WnckWorkspace *wspace = wnck_screen_get_active_workspace (screen);
662

663
	g_assert (foo->windows != NULL);
664

665
	if (wnck_window_is_skip_tasklist (window))
666
		return;
667 668 669 670 671

	name = wnck_window_get_name (window);

	if (name != NULL) {
		slen = strlen (name);
672
		if (slen > 443)
673
			title = g_strdup_printf ("%.420s...%s", name, name + slen - 20);
674
		else
675
			title = g_strdup (name);
676 677 678 679 680 681
	} else {
		/* Translators: Task with no name, should not really happen, so
		 * this should signal that the panel is confused by this task
		 * (thus question marks) */
		title = g_strdup (_("???"));
	}
682

683
	if (wnck_window_is_minimized (window)) {
684
		char *tmp = title;
685 686
		title = g_strdup_printf ("[%s]", title);
		g_free (tmp);
687 688
	}
	
Martin Baulig's avatar
Martin Baulig committed
689
	item = gtk_image_menu_item_new ();
690 691 692 693
	pb = wnck_window_get_mini_icon (window);
	if (pb == NULL)
		pb = get_default_image ();
	if (pb != NULL) {
694 695 696 697 698
		double pix_x, pix_y;
		pix_x = gdk_pixbuf_get_width (pb);
		pix_y = gdk_pixbuf_get_height (pb);
		if (pix_x > ICON_SIZE || pix_y > ICON_SIZE) {
			double greatest;
699
			GdkPixbuf *scaled;
700 701

			greatest = pix_x > pix_y ? pix_x : pix_y;
702 703 704 705 706 707 708 709
			scaled = gdk_pixbuf_scale_simple (pb,
							  (ICON_SIZE / greatest) * pix_x,
							  (ICON_SIZE / greatest) * pix_y,
							  GDK_INTERP_BILINEAR);
			image = gtk_image_new_from_pixbuf (scaled);
			gdk_pixbuf_unref (scaled);
		} else {
			image = gtk_image_new_from_pixbuf (pb);
710
		}
711
		gtk_widget_show (image);
Martin Baulig's avatar
Martin Baulig committed
712 713
		gtk_image_menu_item_set_image (GTK_IMAGE_MENU_ITEM (item),
					       GTK_WIDGET (image));
714 715
	}

716
	label = gtk_label_new (title);
717 718 719 720
	g_free (title);

	gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
	gtk_container_add (GTK_CONTAINER (item), label);
721
	g_hash_table_insert (foo->windows, window, item);
722
	g_signal_connect (G_OBJECT (item), "activate", 
723 724
			  G_CALLBACK (focus_window),
			  window);
725
	gtk_widget_show_all (item);
726
	
727
	if (wspace == wnck_window_get_workspace (window)) {
Martin Baulig's avatar
Martin Baulig committed
728
		gtk_menu_shell_prepend (GTK_MENU_SHELL (foo->task_menu), item);
729
	} else {
Martin Baulig's avatar
Martin Baulig committed
730
		gtk_menu_shell_append (GTK_MENU_SHELL (foo->task_menu), item);
731
	}
732 733 734 735 736 737
}

static void
create_task_menu (GtkWidget *w, gpointer data)
{
	FoobarWidget *foo = FOOBAR_WIDGET (data);
738 739
	GList *list;
	GtkWidget *separator;
740 741
	WnckScreen *screen = wnck_screen_get (0 /* FIXME screen number */);
	GList *windows = wnck_screen_get_windows (screen);
742

743
	/* g_message ("creating..."); */
744
	foo->windows = g_hash_table_new (g_direct_hash, g_direct_equal);
745

746
	separator = add_menu_separator (foo->task_menu);
747

748
	g_list_foreach (windows, (GFunc)add_window, foo);
749

750 751 752 753 754 755 756 757 758
	list = g_list_last (GTK_MENU_SHELL (foo->task_menu)->children);

	if (list != NULL &&
	    separator == list->data) {
		/* if the separator is the last item wipe it.
		 * We leave it as the first though */
		gtk_widget_destroy (separator);
	}

759 760 761 762 763 764 765 766 767 768 769 770 771
	list = g_list_last (GTK_MENU_SHELL (foo->task_menu)->children);
	if (list == NULL) {
		GtkWidget *item;
		item = gtk_image_menu_item_new_with_label (_("No windows open"));
		gtk_widget_set_sensitive (item, FALSE);
		gtk_widget_show_all (item);
	
		gtk_menu_shell_append (GTK_MENU_SHELL (foo->task_menu), item);
	}

	if (GTK_WIDGET_VISIBLE (foo->task_menu))
		our_gtk_menu_position (GTK_MENU (foo->task_menu));

772
	/* Owen: don't read the next line */
773 774 775 776
#if 0
	GTK_MENU_SHELL (foo->task_menu)->active = 1;
	our_gtk_menu_position (GTK_MENU (foo->task_menu));
#endif
777 778 779 780 781 782 783 784
}

static void
destroy_task_menu (GtkWidget *w, gpointer data)
{
	FoobarWidget *foo = FOOBAR_WIDGET (data);
	/*g_message ("removing...");*/
	gtk_menu_item_remove_submenu (GTK_MENU_ITEM (w));
785 786
	g_hash_table_destroy (foo->windows);
	foo->windows = NULL;
787 788
	set_the_task_submenu (foo, w);
}
789 790

static void
791
set_das_pixmap (FoobarWidget *foo, WnckWindow *window)
792
{
793 794
	GdkPixbuf *pb;
	if ( ! GTK_WIDGET_REALIZED (foo))
795 796
		return;

Martin Baulig's avatar
Martin Baulig committed
797 798 799
	if (foo->task_image != NULL)
		gtk_widget_destroy (GTK_WIDGET (foo->task_image));
	foo->task_image = NULL;
800

801 802 803 804 805 806 807
	foo->icon_window = window;

	pb = NULL;
	if (window != NULL)
		pb = wnck_window_get_mini_icon (window);
	if (pb == NULL)
		pb = get_default_image ();
808

809
	if (pb != NULL) {
810 811 812 813 814
		double pix_x, pix_y;
		pix_x = gdk_pixbuf_get_width (pb);
		pix_y = gdk_pixbuf_get_height (pb);
		if (pix_x > ICON_SIZE || pix_y > ICON_SIZE) {
			double greatest;
815
			GdkPixbuf *scaled;
816 817

			greatest = pix_x > pix_y ? pix_x : pix_y;
818 819 820 821 822 823 824 825
			scaled = gdk_pixbuf_scale_simple (pb,
							  (ICON_SIZE / greatest) * pix_x,
							  (ICON_SIZE / greatest) * pix_y,
							  GDK_INTERP_BILINEAR);
			foo->task_image = gtk_image_new_from_pixbuf (scaled);
			gdk_pixbuf_unref (scaled);
		} else {
			foo->task_image = gtk_image_new_from_pixbuf (pb);
826
		}
827
		gtk_widget_show (foo->task_image);
828 829

		gtk_container_add (GTK_CONTAINER (foo->task_bin),
Martin Baulig's avatar
Martin Baulig committed
830
				   GTK_WIDGET (foo->task_image));
831 832 833 834
	}
}

static void
835
append_task_menu (FoobarWidget *foo, GtkMenuShell *menu_bar)
836
{
837
	foo->task_item = gtk_menu_item_new ();
838
	gtk_widget_show (foo->task_item);
839 840 841 842 843 844

	foo->task_bin = gtk_alignment_new (0.3, 0.5, 0.0, 0.0);
	gtk_widget_set_usize (foo->task_bin, 25, 20);
	gtk_widget_show (foo->task_bin);
	gtk_container_add (GTK_CONTAINER (foo->task_item), foo->task_bin);

845
	gtk_menu_shell_append (menu_bar, foo->task_item);
846 847 848

	panel_strech_events_to_toplevel (foo->task_item,
					 TRUE /* top */,
849
					 TRUE /* right */,
850 851 852 853 854 855 856 857 858 859 860 861 862
					 FALSE /* bottom */,
					 FALSE /* left */);
}

static void
icon_changed (WnckWindow *window, FoobarWidget *foo)
{
	set_das_pixmap (foo, window);
}

static void
bind_window_changes (WnckWindow *window, FoobarWidget *foo)
{
863 864 865 866
	panel_signal_connect_while_alive (G_OBJECT (window), "icon_changed",
					  G_CALLBACK (icon_changed),
					  foo,
					  G_OBJECT (foo));
867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906
	/* XXX: do we care about names changing? */
}

/* focused window changed */
static void
active_window_changed (WnckScreen *screen,
		       FoobarWidget *foo)
{
	WnckWindow *window = wnck_screen_get_active_window (screen);

	/* icon might have changed */
	if (foo->icon_window != window)
		set_das_pixmap (foo, window);
}

/* window added */
static void
window_opened (WnckScreen *screen,
	       WnckWindow *window,
	       FoobarWidget *foo)
{
	if (foo->windows != NULL)
		add_window (window, foo);
	bind_window_changes (window, foo);
}
/* window removed */
static void
window_closed (WnckScreen *screen,
	       WnckWindow *window,
	       FoobarWidget *foo)
{
	if (window == foo->icon_window)
		set_das_pixmap (foo, NULL);
	/* FIXME: Whoa; leak? */
	if (foo->windows != NULL) {
		GtkWidget *item;
		item = g_hash_table_lookup (foo->windows, window);
		if (item != NULL) {
			g_hash_table_remove (foo->windows, window);
			gtk_widget_hide (item);
907
			gtk_menu_reposition (GTK_MENU (item->parent));
908 909 910 911 912
		} else {
			g_warning ("Could not find item for task '%s'",
				   sure_string (wnck_window_get_name (window)));
		}
	}
913 914 915 916 917
}

static void
setup_task_menu (FoobarWidget *foo)
{
918 919
	GList *windows;
	WnckScreen *screen;
920 921
	g_assert (foo->task_item != NULL);

922 923 924 925
	g_signal_connect (G_OBJECT (foo->task_item), "select",
			  G_CALLBACK (create_task_menu), foo);
	g_signal_connect (G_OBJECT (foo->task_item), "deselect",
			  G_CALLBACK (destroy_task_menu), foo);
926 927 928

	set_the_task_submenu (foo, foo->task_item);

929 930
	screen = wnck_screen_get (0 /* FIXME screen number */);

931
	/* setup the pixmap to the focused task */
932 933 934 935
	windows = wnck_screen_get_windows (screen);
	while (windows != NULL) {
		if (wnck_window_is_active (windows->data)) {
			set_das_pixmap  (foo, windows->data);
936 937
			break;
		}
938
		windows = windows->next;
939
	}
940

941
	/* if no focused task found, then just set it to default */
942
	if (windows == NULL)
943 944
		set_das_pixmap  (foo, NULL);

945 946
	g_list_foreach (windows, (GFunc)bind_window_changes, foo);

947 948 949 950 951 952 953 954 955 956 957 958 959 960 961
	panel_signal_connect_while_alive (G_OBJECT (screen),
					  "active_window_changed",
					  G_CALLBACK (active_window_changed),
					  foo,
					  G_OBJECT (foo));
	panel_signal_connect_while_alive (G_OBJECT (screen),
					  "window_opened",
					  G_CALLBACK (window_opened),
					  foo,
					  G_OBJECT (foo));
	panel_signal_connect_while_alive (G_OBJECT (screen),
					  "window_closed",
					  G_CALLBACK (window_closed),
					  foo,
					  G_OBJECT (foo));
962

963 964
}

965
static void
966
foobar_widget_instance_init (FoobarWidget *foo)
967
{
968
	/*gchar *path;*/
969
	GtkWindow *window = GTK_WINDOW (foo);
970
	/*GtkWidget *bufmap;*/
971
	GtkWidget *menu_bar, *bar;
972
	GtkWidget *menu, *menuitem;
973
	/*GtkWidget *align;*/
974
	gint flags;
975

976 977
	foo->screen = 0;

978
	foo->windows    = NULL;
979 980
	foo->task_item  = NULL;
	foo->task_menu  = NULL;
Martin Baulig's avatar
Martin Baulig committed
981
	foo->task_image = NULL;
982
	foo->task_bin   = NULL;
983
	foo->icon_window = NULL;
984

985 986 987 988
	foo->clock_format = g_strdup (_("%H:%M"));
	foo->clock_timeout = 0;
	foo->clock_label = NULL;

989
	foo->compliant_wm = xstuff_is_compliant_wm ();
990 991 992 993
	if(foo->compliant_wm)
		GTK_WINDOW(foo)->type = GTK_WINDOW_TOPLEVEL;
	else
		GTK_WINDOW(foo)->type = GTK_WINDOW_POPUP;
994 995 996 997

	window->allow_shrink = TRUE;
	window->allow_grow   = TRUE;

998 999
	g_signal_connect (G_OBJECT (foo), "delete_event",
			  G_CALLBACK (gtk_true), NULL);
1000

1001 1002 1003
	gtk_widget_set_uposition (GTK_WIDGET (foo),
				  multiscreen_x (foo->screen),
				  multiscreen_y (foo->screen));
1004
	gtk_widget_set_usize (GTK_WIDGET (foo),
1005
			      multiscreen_width (foo->screen), -2);
1006

1007
	foo->ebox = gtk_event_box_new ();
1008
	foo->hbox = gtk_hbox_new (FALSE, 0);
1009
	gtk_container_add(GTK_CONTAINER(foo->ebox), foo->hbox);
1010 1011

#if 0	
1012 1013
	path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, 
					  "panel/corner1.png", TRUE, NULL);
1014 1015 1016 1017 1018 1019 1020 1021 1022
	bufmap = gnome_pixmap_new_from_file (path);
	g_free (path);
	align = gtk_alignment_new (0.0, 0.0, 1.0, 0.0);
	gtk_container_add (GTK_CONTAINER (align), bufmap);
	gtk_box_pack_start (GTK_BOX (foo->hbox), align, FALSE, FALSE, 0);
#endif

	menu_bar = gtk_menu_bar_new ();	
	
1023
	menuitem = pixmap_menu_item_new (_("Applications"),
1024
					 "gnome-logo-icon-transparent.png");
1025 1026 1027 1028 1029 1030 1031
	flags = MAIN_MENU_SYSTEM;
	if (got_kde_menus ())
		flags |= MAIN_MENU_KDE_SUB;
	if (got_distro_menus ())
		flags |= MAIN_MENU_DISTRIBUTION_SUB;

	menu = create_root_menu (NULL, TRUE, flags, TRUE, FALSE, FALSE /* run_item */);
1032
	gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), menu);
1033
	gtk_menu_shell_append (GTK_MENU_SHELL (menu_bar), menuitem);
1034 1035 1036
	g_signal_connect (G_OBJECT (menu), "show",
			  G_CALLBACK (programs_menu_to_display),
			  NULL);
1037 1038
	foo->programs = menu;

1039 1040 1041 1042 1043 1044
	/* Strech the applications menu to the corner */
	panel_strech_events_to_toplevel (menuitem,
					 TRUE /* top */,
					 FALSE /* right */,
					 FALSE /* bottom */,
					 TRUE /* left */);
1045 1046

	append_actions_menu (menu_bar);
1047

1048 1049 1050 1051
	gtk_box_pack_start (GTK_BOX (foo->hbox), menu_bar, FALSE, FALSE, 0);
	
	
	/* panel widget */
1052
	foo->panel = panel_widget_new (FALSE, GTK_ORIENTATION_HORIZONTAL,
Mark McLoughlin's avatar
Mark McLoughlin committed
1053
				       PANEL_SIZE_X_SMALL, PANEL_BACK_NONE,
1054
				       NULL, FALSE, FALSE, FALSE, NULL);
1055 1056 1057 1058 1059 1060 1061 1062
	PANEL_WIDGET (foo->panel)->panel_parent = GTK_WIDGET (foo);
	PANEL_WIDGET (foo->panel)->drop_widget = GTK_WIDGET (foo);

	gtk_container_add (GTK_CONTAINER (foo->hbox), foo->panel);

	gtk_object_set_data (GTK_OBJECT (menu_bar), "menu_panel", foo->panel);

#if 0
1063 1064
	path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP, 
					  "panel/corner2.png", TRUE, NULL);
1065 1066 1067 1068 1069 1070 1071
	bufmap = gnome_pixmap_new_from_file (path);
	g_free (path);
	align = gtk_alignment_new (1.0, 0.0, 1.0, 0.0);
	gtk_container_add (GTK_CONTAINER (align), bufmap);
	gtk_box_pack_end (GTK_BOX (foo->hbox), align, FALSE, FALSE, 0);
#endif

1072
	bar = menu_bar = gtk_menu_bar_new ();
1073

1074
	append_clock_menu (foo, menu_bar);
1075

1076
	append_task_menu (foo, GTK_MENU_SHELL (bar));
1077 1078 1079


	gtk_box_pack_end (GTK_BOX (foo->hbox), menu_bar, FALSE, FALSE, 0);
1080 1081
	gtk_container_add (GTK_CONTAINER (foo), foo->ebox);
	gtk_widget_show_all (foo->ebox);
1082 1083 1084
}

static void
1085
queue_panel_resize (gpointer data, gpointer user_data)
1086 1087 1088 1089 1090 1091 1092 1093 1094 1095
{
	PanelData *pd = data;
	GtkWidget *panel;

	g_assert (pd);

	panel = pd->panel;

	g_return_if_fail (GTK_IS_WIDGET (panel));

1096
	if (!DRAWER_IS_WIDGET (panel) && !FOOBAR_IS_WIDGET (panel))
1097 1098 1099
		gtk_widget_queue_resize (panel);
}

1100
static void
1101
foobar_widget_destroy (GtkObject *o)
1102
{
1103 1104
	FoobarWidget *foo = FOOBAR_WIDGET (o);

1105
	foobars = g_list_remove (foobars, foo);
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115

	if (foo->clock_timeout != 0)
		gtk_timeout_remove (foo->clock_timeout);
	foo->clock_timeout = 0;
	
	foo->clock_label = NULL;

	g_free (foo->clock_format);
	foo->clock_format = NULL;

1116
	g_slist_foreach (panel_list, queue_panel_resize, NULL);
1117

1118 1119 1120
	if (foo->windows != NULL)
		g_hash_table_destroy (foo->windows);
	foo->windows = NULL;
1121

1122 1123
	if (GTK_OBJECT_CLASS (foobar_widget_parent_class)->destroy)
		GTK_OBJECT_CLASS (foobar_widget_parent_class)->destroy (o);
1124 1125
}

1126
static void
1127
foobar_widget_size_allocate (GtkWidget *w, GtkAllocation *alloc)
1128
{
1129 1130
	if (GTK_WIDGET_CLASS (foobar_widget_parent_class)->size_allocate)
		GTK_WIDGET_CLASS (foobar_widget_parent_class)->size_allocate (w, alloc);
1131

1132
	if (GTK_WIDGET_REALIZED (w)) {
1133 1134 1135 1136 1137 1138 1139
		FoobarWidget *foo = FOOBAR_WIDGET (w);
		xstuff_set_pos_size (w->window,
				     multiscreen_x (foo->screen),
				     multiscreen_y (foo->screen),
				     alloc->width,
				     alloc->height);

1140
		g_slist_foreach (panel_list, queue_panel_resize, NULL);
1141
		basep_border_queue_recalc (foo->screen);
1142 1143 1144 1145 1146 1147

		xstuff_set_wmspec_strut (w->window,
					 0 /* left */,
					 0 /* right */,
					 alloc->height /* top */,
					 0 /* bottom */);
1148
	}
1149 1150
}

1151
GtkWidget *
1152
foobar_widget_new (int screen)
1153
{
1154 1155 1156 1157 1158 1159
	FoobarWidget *foo;

	g_return_val_if_fail (screen >= 0, NULL);

	if (foobar_widget_exists (screen))
		return NULL;
1160

1161
	foo = gtk_type_new (FOOBAR_TYPE_WIDGET);
1162

1163 1164 1165 1166 1167 1168
	foo->screen = screen;
	gtk_widget_set_uposition (GTK_WIDGET (foo),
				  multiscreen_x (foo->screen),
				  multiscreen_y (foo->screen));
	gtk_widget_set_usize (GTK_WIDGET (foo),
			      multiscreen_width (foo->screen), -2);
1169

1170
	foobars = g_list_prepend (foobars, foo);
1171

1172
	return GTK_WIDGET (foo);
1173 1174 1175
}

gboolean
1176
foobar_widget_exists (int screen)
1177
{
1178
	GList *li;
1179

1180 1181 1182 1183 1184 1185 1186
	for (li = foobars; li != NULL; li = li->next) {
		FoobarWidget *foo = li->data;

		if (foo->screen == screen)
			return TRUE;
	}
	return FALSE;
1187 1188
}

1189 1190 1191 1192
void
foobar_widget_force_menu_remake (void)
{
	FoobarWidget *foo;
1193
	GList *li;
1194

1195 1196
	for (li = foobars; li != NULL; li = li->next) {
		foo = FOOBAR_WIDGET(li->data);
1197 1198 1199 1200 1201

		if (foo->programs != NULL)
			gtk_object_set_data (GTK_OBJECT(foo->programs),
					     "need_reread", GINT_TO_POINTER(1));
	}
1202 1203
}

1204
gint
1205
foobar_widget_get_height (int screen)
1206
{
1207
	GList *li;
1208

1209
	g_return_val_if_fail (screen >= 0, 0);
1210

1211 1212 1213 1214 1215 1216 1217
	for (li = foobars; li != NULL; li = li->next) {
		FoobarWidget *foo = FOOBAR_WIDGET(li->data);

		if (foo->screen == screen)
			return GTK_WIDGET (foo)->allocation.height;
	}
	return 0; 
1218
}
1219 1220 1221 1222 1223

static void
reparent_button_widgets(GtkWidget *w, gpointer data)
{
	GdkWindow *newwin = data;
1224
	if (BUTTON_IS_WIDGET (w)) {
1225 1226 1227 1228
		ButtonWidget *button = BUTTON_WIDGET(w);
		/* we can just reparent them all to 0,0 as the next thing
		 * that will happen is a queue_resize and on size allocate
		 * they will be put into their proper place */
1229
		gdk_window_reparent (button->event_window, newwin, 0, 0);
1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244
	}
}

void
foobar_widget_redo_window(FoobarWidget *foo)
{
	GtkWindow *window;
	GtkWidget *widget;
	GdkWindowAttr attributes;
	gint attributes_mask;
	GdkWindow *oldwin;
	GdkWindow *newwin;
	gboolean comp;

	comp = xstuff_is_compliant_wm();
1245
	if (comp == foo->compliant_wm)
1246 1247 1248 1249 1250 1251
		return;

	window = GTK_WINDOW(foo);
	widget = GTK_WIDGET(foo);

	foo->compliant_wm = comp;
1252
	if (foo->compliant_wm) {
1253 1254 1255 1256 1257 1258 1259
		window->type = GTK_WINDOW_TOPLEVEL;
		attributes.window_type = GDK_WINDOW_TOPLEVEL;
	} else {
		window->type = GTK_WINDOW_POPUP;
		attributes.window_type = GDK_WINDOW_TEMP;
	}

1260
	if (widget->window == NULL)
1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288
		return;

	/* this is mostly copied from gtkwindow.c realize method */
	attributes.title = window->title;
	attributes.wmclass_name = window->wmclass_name;
	attributes.wmclass_class = window->wmclass_class;
	attributes.width = widget->allocation.width;
	attributes.height = widget->allocation.height;
	attributes.wclass = GDK_INPUT_OUTPUT;
	attributes.visual = gtk_widget_get_visual (widget);
	attributes.colormap = gtk_widget_get_colormap (widget);
	attributes.event_mask = gtk_widget_get_events (widget);
	attributes.event_mask |= (GDK_EXPOSURE_MASK |
				  GDK_KEY_PRESS_MASK |
				  GDK_ENTER_NOTIFY_MASK |
				  GDK_LEAVE_NOTIFY_MASK |
				  GDK_FOCUS_CHANGE_MASK |
				  GDK_STRUCTURE_MASK);

	attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP;
	attributes_mask |= (window->title ? GDK_WA_TITLE : 0);
	attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0);
   
	oldwin = widget->window;

	newwin = gdk_window_new(NULL, &attributes, attributes_mask);
	gdk_window_set_user_data(newwin, window);

1289
	xstuff_set_no_group_and_no_input (newwin);
1290

1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313
	/* reparent our main panel window */
	gdk_window_reparent(foo->ebox->window, newwin, 0, 0);
	/* reparent all the base event windows as they are also children of
	 * the foobar */
	gtk_container_foreach(GTK_CONTAINER(foo->panel),
			      reparent_button_widgets,
			      newwin);


	widget->window = newwin;

	gdk_window_set_user_data(oldwin, NULL);
	gdk_window_destroy(oldwin);

	widget->style = gtk_style_attach(widget->style, widget->window);
	gtk_style_set_background(widget->style, widget->window, GTK_STATE_NORMAL);

	GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);

	gtk_widget_queue_resize(widget);

	foobar_widget_update_winhints (foo);

1314 1315 1316 1317 1318 1319
	xstuff_set_wmspec_strut (widget->window,