panel.c 24.9 KB
Newer Older
1
/* Gnome panel: Initialization routines
Elliot Lee's avatar
Elliot Lee committed
2 3
 * (C) 1997 the Free Software Foundation
 *
4 5 6
 * Authors: Federico Mena
 *          Miguel de Icaza
 *          George Lebl
Elliot Lee's avatar
Elliot Lee committed
7 8
 */

9
#include <config.h>
Elliot Lee's avatar
Elliot Lee committed
10
#include <string.h>
11
#include <signal.h>
12
#include <unistd.h>
13
#include <sys/types.h>
14
#include <sys/stat.h>
15
#include <sys/wait.h>
16
#include <gnome.h>
17

18
#include "panel-include.h"
19
#include "gnome-panel.h"
20 21

#define PANEL_EVENT_MASK (GDK_BUTTON_PRESS_MASK |		\
22 23 24
			   GDK_BUTTON_RELEASE_MASK |		\
			   GDK_POINTER_MOTION_MASK |		\
			   GDK_POINTER_MOTION_HINT_MASK)
25

26
/*list of all panel widgets created*/
27
GSList *panel_list = NULL;
28

29 30 31
static int panel_dragged = FALSE;
static int panel_dragged_timeout = -1;
static int panel_been_moved = FALSE;
32

George Lebl's avatar
George Lebl committed
33 34
/*the number of base panels (corner/snapped) out there, never let it
  go below 1*/
35 36
int base_panels = 0;

37
extern int config_sync_timeout;
38
extern int applets_to_sync;
39
extern int panels_to_sync;
40 41
extern int need_complete_save;

42 43
extern GlobalConfig global_config;

44
extern GtkTooltips *panel_tooltips;
45

46 47 48 49 50
/*???? this might be ugly, but I guess we can safely assume that we can only
  have one menu open and that nothing weird will happen to the panel that
  opened that menu whilethe user is looking over the choices*/
extern PanelWidget *current_panel;

51
/*the types of stuff we accept*/
Owen Taylor's avatar
Owen Taylor committed
52 53 54

enum {
	TARGET_URL,
55
	TARGET_NETSCAPE_URL,
56 57
	TARGET_DIRECTORY,
	TARGET_COLOR,
58 59
	TARGET_APPLET,
	TARGET_APPLET_INTERNAL
Owen Taylor's avatar
Owen Taylor committed
60 61 62 63
};

static GtkTargetEntry panel_drop_types[] = {
	{ "text/uri-list",       0, TARGET_URL },
64 65
	{ "x-url/http",          0, TARGET_NETSCAPE_URL },
	{ "x-url/ftp",           0, TARGET_NETSCAPE_URL },
66
	{ "_NETSCAPE_URL",       0, TARGET_NETSCAPE_URL },
67 68
	{ "application/x-panel-directory", 0, TARGET_DIRECTORY },
	{ "application/x-panel-applet", 0, TARGET_APPLET },
69
	{ "application/x-panel-applet-internal", 0, TARGET_APPLET_INTERNAL },
Owen Taylor's avatar
Owen Taylor committed
70 71 72 73 74
	{ "application/x-color", 0, TARGET_COLOR }
};

static gint n_panel_drop_types = 
   sizeof(panel_drop_types) / sizeof(panel_drop_types[0]);
75

76
#if 0
77 78
static PanelData *
get_lowest_level_master_pd(PanelWidget *panel)
79
{
80 81
	GtkObject *parent;
	PanelData *pd;
82

83
	while(panel->master_widget)
84
		panel = PANEL_WIDGET(panel->master_widget->parent);
85 86
	parent = gtk_object_get_data(GTK_OBJECT(panel),PANEL_PARENT);
	g_return_val_if_fail(parent!=NULL,NULL);
87
	
88 89 90 91
	pd = gtk_object_get_user_data(parent);
	g_return_val_if_fail(pd!=NULL,NULL);
	
	return pd;
Elliot Lee's avatar
Elliot Lee committed
92
}
93
#endif
94
static void
95 96 97 98 99
change_window_cursor(GdkWindow *window, GdkCursorType cursor_type)
{
	GdkCursor *cursor = gdk_cursor_new(cursor_type);
	gdk_window_set_cursor(window, cursor);
	gdk_cursor_destroy(cursor);
100 101
}

102
static void
103
panel_realize(GtkWidget *widget, gpointer data)
Elliot Lee's avatar
Elliot Lee committed
104
{
105
	change_window_cursor(widget->window, GDK_LEFT_PTR);
106
	
107
	basep_widget_enable_buttons(BASEP_WIDGET(widget));
108 109 110
	/*FIXME: this seems to fix the panel size problems on startup
	  (from a report) but I don't think it's right*/
	gtk_widget_queue_resize(GTK_WIDGET(widget));
111 112
}

113 114 115 116 117 118 119 120 121 122 123 124 125 126
PanelOrientType
get_applet_orient (PanelWidget *panel)
{
	GtkWidget *panelw = gtk_object_get_data (GTK_OBJECT(panel),
						 PANEL_PARENT);
	g_assert (IS_BASEP_WIDGET (panelw));

	if (IS_BASEP_WIDGET(panelw))
		return basep_widget_get_applet_orient (BASEP_WIDGET(panelw));
	else
		g_assert_not_reached ();
	return ORIENT_UP;
}

127
/*we call this recursively*/
128
static void orient_change_foreach(GtkWidget *w, gpointer data);
129

130
void
131
orientation_change(AppletInfo *info, PanelWidget *panel)
132
{
133 134 135 136
	if(info->type == APPLET_EXTERN) {
		Extern *ext = info->data;
		g_assert(ext);
		/*ingore this until we get an ior*/
137 138 139 140 141 142 143 144 145 146
		if(ext->applet) {
			CORBA_Environment ev;
			CORBA_exception_init(&ev);
			GNOME_Applet_change_orient(ext->applet,
						   get_applet_orient(panel),
						   &ev);
			if(ev._major)
				panel_clean_applet(ext->info);
			CORBA_exception_free(&ev);
		}
147 148 149 150 151
	} else if(info->type == APPLET_MENU) {
		Menu *menu = info->data;
		set_menu_applet_orient(menu,get_applet_orient(panel));
	} else if(info->type == APPLET_DRAWER) {
		Drawer *drawer = info->data;
152
		BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
153
		set_drawer_applet_orient(drawer,get_applet_orient(panel));
154
		gtk_widget_queue_resize(drawer->drawer);
155
		gtk_container_foreach(GTK_CONTAINER(basep->panel),
156
				      orient_change_foreach,
157
				      (gpointer)basep->panel);
158 159 160 161 162 163 164
	} else if(info->type == APPLET_SWALLOW) {
		Swallow *swallow = info->data;

		if(panel->orient == PANEL_VERTICAL)
			set_swallow_applet_orient(swallow,SWALLOW_VERTICAL);
		else
			set_swallow_applet_orient(swallow,SWALLOW_HORIZONTAL);
165 166 167 168
	} else if(info->type == APPLET_STATUS) {
		StatusApplet *status = info->data;
		status->orient = panel->orient;
		status_applet_update(status);
169 170 171
	}
}

172
static void
173
orient_change_foreach(GtkWidget *w, gpointer data)
174
{
175
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
176
	PanelWidget *panel = data;
177
	
178
	orientation_change(info,panel);
179 180
}

181

182 183 184 185 186
static void
panel_orient_change(GtkWidget *widget,
		    PanelOrientation orient,
		    gpointer data)
{
187 188
	gtk_container_foreach(GTK_CONTAINER(widget),
			      orient_change_foreach,
189
			      widget);
190
	panels_to_sync = TRUE;
191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228
}

static void
border_edge_change (BorderPos *border,
		    BorderEdge edge,
		    gpointer data)
{
	BasePWidget *basep = BASEP_WIDGET (data);
	PanelWidget *panel = PANEL_WIDGET (basep->panel);
	gtk_container_foreach (GTK_CONTAINER (panel),
			       orient_change_foreach,
			       panel);
	panels_to_sync = TRUE;
	update_config_edge (basep);
}

static void
sliding_anchor_change (SlidingPos *pos,
		       SlidingAnchor anchor,
		       gpointer data)
{
	update_config_anchor (BASEP_WIDGET (data));
}

static void
sliding_offset_change (SlidingPos *pos,
		       gint16 offset,
		       gpointer data)
{
	update_config_offset (BASEP_WIDGET (data));
}

static void
aligned_align_change (AlignedPos *pos,
		      AlignedAlignment align,
		      gpointer data)
{
	update_config_align (BASEP_WIDGET (data));
229 230
}

231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250
/*we call this recursively*/
static void size_change_foreach(GtkWidget *w, gpointer data);

void
size_change(AppletInfo *info, PanelWidget *panel)
{
	if(info->type == APPLET_EXTERN) {
		Extern *ext = info->data;
		g_assert(ext);
		/*ingore this until we get an ior*/
		if(ext->applet) {
			CORBA_Environment ev;
			CORBA_exception_init(&ev);
			GNOME_Applet_change_size(ext->applet,
						 panel->sz,
						 &ev);
			if(ev._major)
				panel_clean_applet(ext->info);
			CORBA_exception_free(&ev);
		}
251 252
	} else if(info->type == APPLET_STATUS) {
		StatusApplet *status = info->data;
253
		status->size = panel->sz;
254
		status_applet_update(status);
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
	}
}

static void
size_change_foreach(GtkWidget *w, gpointer data)
{
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
	PanelWidget *panel = data;
	
	size_change(info,panel);
}


static void
panel_size_change(GtkWidget *widget,
		  PanelSizeType sz,
		  gpointer data)
{
	gtk_container_foreach(GTK_CONTAINER(widget), size_change_foreach,
			      widget);
	panels_to_sync = TRUE;
	/*update the configuration box if it is displayed*/
	update_config_size(gtk_object_get_data(GTK_OBJECT(widget),
					       PANEL_PARENT));
}

281
void
282
back_change(AppletInfo *info, PanelWidget *panel)
283
{
284 285 286 287
	if(info->type == APPLET_EXTERN) {
		Extern *ext = info->data;
		g_assert(ext);
		/*ignore until we have a valid IOR*/
288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
		if(ext->applet) {
			GNOME_Panel_BackInfoType backing;
			CORBA_Environment ev;
			CORBA_exception_init(&ev);
			backing._d = panel->back_type;
			if(panel->back_type == PANEL_BACK_PIXMAP)
				backing._u.pmap = panel->back_pixmap;
			else if(panel->back_type == PANEL_BACK_COLOR) {
				backing._u.c.red = panel->back_color.red;
				backing._u.c.green = panel->back_color.green;
				backing._u.c.blue = panel->back_color.blue;
			}
			GNOME_Applet_back_change(ext->applet, &backing, &ev);
			if(ev._major)
				panel_clean_applet(ext->info);
			CORBA_exception_free(&ev);
		}
305
	} 
Elliot Lee's avatar
Elliot Lee committed
306 307
}

308

Elliot Lee's avatar
Elliot Lee committed
309
static void
310
back_change_foreach(GtkWidget *w, gpointer data)
Elliot Lee's avatar
Elliot Lee committed
311
{
312
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
313
	PanelWidget *panel = data;
314

315
	back_change(info,panel);
Elliot Lee's avatar
Elliot Lee committed
316 317
}

318 319 320 321 322
static void
panel_back_change(GtkWidget *widget,
		  PanelBackType type,
		  char *pixmap,
		  GdkColor *color)
323
{
324
	gtk_container_foreach(GTK_CONTAINER(widget),back_change_foreach,widget);
325

326 327
	panels_to_sync = TRUE;
	/*update the configuration box if it is displayed*/
328
	update_config_back(PANEL_WIDGET(widget));
329 330
}

331
static void state_hide_foreach(GtkWidget *w, gpointer data);
332 333

static void
334
state_restore_foreach(GtkWidget *w, gpointer data)
Elliot Lee's avatar
Elliot Lee committed
335
{
336
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
337 338
	
	if(info->type == APPLET_DRAWER) {
339
		Drawer *drawer = info->data;
340
		BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
341 342 343 344 345 346 347 348 349

		DRAWER_POS (basep->pos)->temp_hidden = FALSE;
		gtk_widget_queue_resize (GTK_WIDGET (basep));

		gtk_container_foreach (GTK_CONTAINER (basep->panel),
				       (basep->state == BASEP_SHOWN)
				       ? state_restore_foreach
				       : state_hide_foreach,
				       NULL);
350
	}
Elliot Lee's avatar
Elliot Lee committed
351 352
}

353
static void
354
state_hide_foreach(GtkWidget *w, gpointer data)
355
{
356
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
357 358
	if(info->type == APPLET_DRAWER) {
		Drawer *drawer = info->data;
359
		BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
360 361

		DRAWER_POS (basep->pos)->temp_hidden = TRUE;
362
		gtk_container_foreach(GTK_CONTAINER(basep->panel),
363 364
				      state_hide_foreach,
				      NULL);
365 366

		gtk_widget_queue_resize (GTK_WIDGET (basep));
367
	}
368 369
}

370 371
static void
queue_resize_foreach(GtkWidget *w, gpointer data)
Elliot Lee's avatar
Elliot Lee committed
372
{
373
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(w), "applet_info");
374

375 376 377 378 379 380 381 382 383 384 385
	if(info->type == APPLET_DRAWER) {
		Drawer *drawer = info->data;
		BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
		
		if(basep->state == BASEP_SHOWN) {
			gtk_widget_queue_resize(w);
			gtk_container_foreach(GTK_CONTAINER(basep->panel),
					       queue_resize_foreach,
					       NULL);
		}
	}
Elliot Lee's avatar
Elliot Lee committed
386
}
387 388

static int
389 390 391
basep_state_change(GtkWidget *widget,
		   BasePState state,
		   gpointer data)
392
{
393 394 395 396 397 398
	BasePWidget *basep = BASEP_WIDGET(widget);
	gtk_container_foreach (GTK_CONTAINER (basep->panel),
			       (state == BASEP_SHOWN)
			       ? state_restore_foreach
			       : state_hide_foreach,
			       (gpointer)widget);
399 400 401 402

	panels_to_sync = TRUE;

	return TRUE;
403 404
}

405 406
static void
panel_applet_added(GtkWidget *widget, GtkWidget *applet, gpointer data)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
407
{
408 409
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(applet),
					       "applet_info");
410 411
	GtkWidget *panelw = gtk_object_get_data(GTK_OBJECT(widget),
						PANEL_PARENT);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
412
	
413 414 415 416
	/*on a real add the info will be NULL as the only adding
	  is done in register_toy and that doesn't add the info to the
	  array until after the add, so we can be sure this was
	  generated on a reparent*/
417 418
	if((IS_BASEP_WIDGET(panelw) &&
	    !IS_DRAWER_WIDGET(panelw)) &&
419
	   info && info->type == APPLET_DRAWER) {
420
	        Drawer *drawer = info->data;
421 422 423 424 425
		BasePWidget *basep = BASEP_WIDGET(drawer->drawer);
		if(basep->state == BASEP_SHOWN ||
		   basep->state == BASEP_AUTO_HIDDEN) {
			BASEP_WIDGET(panelw)->drawers_open++;
			basep_widget_autoshow(BASEP_WIDGET(panelw));
426
		}
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
427
	}
428
	
429
	/*pop the panel up on addition*/
430 431
	if(IS_BASEP_WIDGET(panelw)) {
		basep_widget_autoshow(BASEP_WIDGET(panelw));
432
		/*try to pop down though if the mouse is out*/
433
		basep_widget_queue_autohide(BASEP_WIDGET(panelw));
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
434
	}
435

436 437 438
	orientation_change(info,PANEL_WIDGET(BASEP_WIDGET(panelw)->panel));
	size_change(info,PANEL_WIDGET(BASEP_WIDGET(panelw)->panel));
	back_change(info,PANEL_WIDGET(BASEP_WIDGET(panelw)->panel));
439 440

	/*we will need to save this applet's config now*/
441
	applets_to_sync = TRUE;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
442 443
}

444
static void
445
panel_applet_removed(GtkWidget *widget, GtkWidget *applet, gpointer data)
Elliot Lee's avatar
Elliot Lee committed
446
{
447 448
	GtkWidget *parentw = gtk_object_get_data(GTK_OBJECT(widget),
						 PANEL_PARENT);
449 450
	AppletInfo *info = gtk_object_get_data(GTK_OBJECT(applet),
					       "applet_info");
451 452

	/*we will need to save this applet's config now*/
453
	applets_to_sync = TRUE;
454 455 456

	if(info->type == APPLET_DRAWER) {
		Drawer *drawer = info->data;
457 458 459 460 461 462
		if((drawer->drawer) && (
			(BASEP_WIDGET(drawer->drawer)->state == BASEP_SHOWN) ||
			(BASEP_WIDGET(drawer->drawer)->state == BASEP_AUTO_HIDDEN))) {
			if(IS_BASEP_WIDGET(parentw)) {
				BASEP_WIDGET(parentw)->drawers_open--;
				basep_widget_queue_autohide(BASEP_WIDGET(parentw));
463 464 465 466 467
			}
		}
		/*it was a drawer so we need to save panels as well*/
		panels_to_sync = TRUE;
	}
468
}
Elliot Lee's avatar
Elliot Lee committed
469 470

static void
471
menu_deactivate(GtkWidget *w, PanelData *pd)
Elliot Lee's avatar
Elliot Lee committed
472
{
473
	pd->menu_age = 0;
474 475
	if(IS_BASEP_WIDGET(pd->panel))
		BASEP_WIDGET(pd->panel)->autohide_inhibit = FALSE;
476 477
}

478 479
static void
move_panel_to_cursor(GtkWidget *w)
480
{
481 482
	int x,y;
	gdk_window_get_pointer(NULL,&x,&y,NULL);
483 484
	if(IS_BASEP_WIDGET(w))
		basep_widget_set_pos(BASEP_WIDGET(w),x,y);
485
}
486

487
static int
488
panel_move_timeout(gpointer data)
489
{
490 491 492 493 494
	if(panel_dragged && panel_been_moved)
		move_panel_to_cursor(data);
	
	panel_been_moved = FALSE;
	panel_dragged_timeout = -1;
495

496
	return FALSE;
497 498
}

499
static void
500
panel_destroy(GtkWidget *widget, gpointer data)
501
{
502 503
	PanelData *pd = gtk_object_get_user_data(GTK_OBJECT(widget));

504 505
	kill_config_dialog(widget);

506
	if(IS_DRAWER_WIDGET(widget)) {
507
		PanelWidget *panel = PANEL_WIDGET(BASEP_WIDGET(widget)->panel);
508
		if(panel->master_widget) {
509 510
			AppletInfo *info = gtk_object_get_data(GTK_OBJECT(panel->master_widget),
							       "applet_info");
511 512
			Drawer *drawer = info->data;
			drawer->drawer = NULL;
513
			panel_clean_applet(info);
514
		}
515 516
	} else if(IS_BASEP_WIDGET(widget) &&
		  !IS_DRAWER_WIDGET(widget)) {
517 518 519
		/*this is a base panel and we just lost it*/
		base_panels--;
	}
520

521 522
	if(pd->menu)
		gtk_widget_destroy(pd->menu);
523
	
524
	panel_list = g_slist_remove(panel_list,pd);
525
	g_free(pd);
526 527
}

528
static void
529
panel_applet_move(GtkWidget *panel,GtkWidget *widget, gpointer data)
530
{
531
	applets_to_sync = TRUE;
532 533 534 535 536 537 538
}

static GtkWidget *
panel_menu_get(PanelData *pd)
{
	if(pd->menu)
		return pd->menu;
539
	
540
	pd->menu = create_panel_root_menu(pd->panel,TRUE);
541 542 543
	gtk_signal_connect(GTK_OBJECT(pd->menu), "deactivate",
			   GTK_SIGNAL_FUNC(menu_deactivate),pd);
	return pd->menu;
544 545
}

546
static int
547
panel_event(GtkWidget *widget, GdkEvent *event, PanelData *pd)
548
{
549
	BasePWidget *basep = BASEP_WIDGET(widget);
550 551 552 553 554 555 556
	GdkEventButton *bevent;
	switch (event->type) {
	case GDK_BUTTON_PRESS:
		bevent = (GdkEventButton *) event;
		switch(bevent->button) {
		case 3: /* fall through */
			if(!panel_applet_in_drag) {
557 558
				GtkWidget *panel_menu;
				GtkWidget *rem;
559
				current_panel =
560
					PANEL_WIDGET(basep->panel);
561 562 563
				panel_menu = panel_menu_get(pd);
				rem = gtk_object_get_data(GTK_OBJECT(panel_menu),
							  "remove_item");
564 565 566 567 568 569 570
				
				if (!IS_DRAWER_WIDGET(basep))
					gtk_widget_set_sensitive(rem, base_panels > 1);

				basep->autohide_inhibit = TRUE;
				basep_widget_queue_autohide(basep);

571
				pd->menu_age = 0;
572
				
573
				gtk_menu_popup(GTK_MENU(panel_menu), NULL, NULL,
574 575
					       global_config.off_panel_popups?
					        panel_menu_position:NULL,
576 577 578 579 580 581 582 583
					       widget, bevent->button,
					       bevent->time);
				return TRUE;
			}
			break;
		case 2:
			/*this should probably be in snapped widget*/
			if(!panel_dragged &&
584
			   !IS_DRAWER_WIDGET (widget)) {
585 586 587 588 589 590 591 592 593
				GdkCursor *cursor = gdk_cursor_new (GDK_FLEUR);
				gtk_grab_add(widget);
				gdk_pointer_grab (widget->window,
						  FALSE,
						  PANEL_EVENT_MASK,
						  NULL,
						  cursor,
						  bevent->time);
				gdk_cursor_destroy (cursor);
594 595 596
				
				basep->autohide_inhibit = TRUE;

597
				panel_dragged = TRUE;
598
				return TRUE;
599
			}
600 601
			if(IS_DRAWER_WIDGET(widget) &&
			   !panel_applet_in_drag) {
602 603
				BasePWidget *basep = BASEP_WIDGET(widget);
				PanelWidget *pw = PANEL_WIDGET(basep->panel);
604 605 606 607
				panel_widget_applet_drag_start(PANEL_WIDGET(pw->master_widget->parent),
							       pw->master_widget);
				return TRUE;
			}
608
			break;
609
		default: break;
610
		}
611
		break;
612

613 614 615
	case GDK_BUTTON_RELEASE:
		bevent = (GdkEventButton *) event;
		if(panel_dragged) {
616 617 618 619 620 621 622

			basep_widget_set_pos(basep,
					     (gint16)bevent->x_root, 
					     (gint16)bevent->y_root);
			basep->autohide_inhibit = FALSE;
			basep_widget_queue_autohide(BASEP_WIDGET(widget));

623 624
			gdk_pointer_ungrab(bevent->time);
			gtk_grab_remove(widget);
625 626 627
			panel_dragged = FALSE;
			panel_dragged_timeout = -1;
			panel_been_moved = FALSE;
628 629
			return TRUE;
		}
630

631
		break;
632 633 634 635 636
	case GDK_MOTION_NOTIFY:
		if (panel_dragged) {
			if(panel_dragged_timeout==-1) {
				panel_been_moved = FALSE;
				move_panel_to_cursor(widget);
637
				panel_dragged_timeout = gtk_timeout_add (30,panel_move_timeout,widget);
638 639 640 641
			} else
				panel_been_moved = TRUE;
		}
		break;
642

643 644 645
	default:
		break;
	}
646

647 648
	return FALSE;
}
649

650
static int
651
panel_sub_event_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
652
{
653 654 655 656
	GdkEventButton *bevent;
	switch (event->type) {
		/*pass these to the parent!*/
		case GDK_BUTTON_PRESS:
657
	        case GDK_BUTTON_RELEASE:
658
	        case GDK_MOTION_NOTIFY:
659 660 661 662
			bevent = (GdkEventButton *) event;
			/*if the widget is a button we want to keep the
			  button 1 events*/
			if(!GTK_IS_BUTTON(widget) || bevent->button!=1)
663
				return gtk_widget_event(data, event);
664

665
			break;
666

667 668
		default:
			break;
669
	}
670

671
	return FALSE;
Arturo Espinosa's avatar
Arturo Espinosa committed
672 673
}

674
static void
675
panel_widget_dnd_drop_internal (GtkWidget	 *widget,
Owen Taylor's avatar
Owen Taylor committed
676 677 678 679 680 681
				GdkDragContext   *context,
				gint              x,
				gint              y,
				GtkSelectionData *selection_data,
				guint             info,
				guint             time)
682 683
{
	PanelWidget *panel;
684
	int pos;
685 686

	g_return_if_fail(widget!=NULL);
687
	g_return_if_fail(IS_BASEP_WIDGET(widget));
688

689 690 691 692
	panel = PANEL_WIDGET (BASEP_WIDGET (widget)->panel);

	pos = panel_widget_get_cursorloc(panel);
	
693 694 695
	/* -1 passed to register_toy will turn on the insert_at_pos
	   flag for panel_widget_add_full, which will not place it
	   after the first applet */
696
	if(pos < 0)
697
		pos = -1;
698 699
	else if(pos > panel->size)
		pos = panel->size;
700

Owen Taylor's avatar
Owen Taylor committed
701 702
	switch (info) {
	case TARGET_URL: {
703
		GList *ltmp, *files;
704
		struct stat s;
705 706 707 708 709

		files =
		  gnome_uri_list_extract_filenames(selection_data->data);

		for(ltmp = files; ltmp; ltmp = g_list_next(ltmp)) {
710
		  const char *mimetype;
711 712

		  mimetype = gnome_mime_type(ltmp->data);
713 714 715 716 717 718

		  if(mimetype &&
		     (!strcmp(mimetype,"x-url/http") ||
		      !strcmp(mimetype,"x-url/ftp"))) {
			  char *exec[3] = {
			  	"gnome-moz-remote",
719
				NULL,
720 721 722 723
				NULL
			  };
			  char *p;

724
		          exec[1] = ltmp->data;
725
			  p = g_strdup_printf("Open URL: %s",
726
					      (char *)ltmp->data);
727 728 729 730 731 732 733 734 735 736 737
			  load_launcher_applet_from_info(ltmp->data,
							 p,exec,2,
							 "netscape.png",
							 panel,pos);
			  g_free(p);
		  }

		  if(stat(ltmp->data, &s) != 0) {
			  continue;
		  }

738 739 740 741 742
		  if(mimetype && !strncmp(mimetype, "image", sizeof("image")-1))
		    panel_widget_set_back_pixmap (panel, ltmp->data);
		  else if(mimetype
			  && !strcmp(mimetype, "application/x-gnome-app-info"))
		    load_launcher_applet(ltmp->data, panel, pos);
743 744 745 746 747 748
		  else if(S_ISDIR(s.st_mode)) {
			  int flags = MAIN_MENU_SYSTEM|MAIN_MENU_USER;

			  /*guess redhat menus*/
			  if(g_file_exists("/etc/X11/wmconfig"))
				  flags |= MAIN_MENU_REDHAT|MAIN_MENU_REDHAT_SUB;
749 750 751 752
			  /* Guess KDE menus */
			  if(g_file_exists(KDE_MENUDIR))
				  flags |= MAIN_MENU_KDE|MAIN_MENU_KDE_SUB;
			  load_menu_applet(ltmp->data, flags, panel, pos);
753
		  } else if(S_IEXEC & s.st_mode) /*executable?*/
754
		    ask_about_launcher(ltmp->data,panel,pos);
755
		}
756
		
Owen Taylor's avatar
Owen Taylor committed
757 758 759
		gnome_uri_list_free_strings (files);
		break;
	}
760
	case TARGET_NETSCAPE_URL: {
761 762
		char *exec[3] = {
			"gnome-moz-remote",
763
			NULL,
764 765
			NULL
		};
766 767
		char *p;
		
768
         	exec[1] = selection_data->data;
769 770 771
		p = g_strdup_printf("Open URL: %s",selection_data->data);
		load_launcher_applet_from_info(selection_data->data,p,exec,2,
					       "netscape.png",panel,pos);
772
		g_free(p);
773 774
		break;
	}
Owen Taylor's avatar
Owen Taylor committed
775 776
	case TARGET_COLOR: {
		guint16 *dropped;
777 778
		GdkColor c;

Owen Taylor's avatar
Owen Taylor committed
779
		dropped = (guint16 *)selection_data->data;
780

Owen Taylor's avatar
Owen Taylor committed
781 782 783
		c.red = dropped[0];
		c.green = dropped[1];
		c.blue = dropped[2];
784 785 786
		c.pixel = 0;

		panel_widget_set_back_color(panel, &c);
Owen Taylor's avatar
Owen Taylor committed
787 788
		break;
	}
789
	case TARGET_DIRECTORY: {
790 791 792 793 794
		int flags = MAIN_MENU_SYSTEM|MAIN_MENU_USER;

		/*guess redhat menus*/
		if(g_file_exists("/etc/X11/wmconfig"))
			flags |= MAIN_MENU_REDHAT|MAIN_MENU_REDHAT_SUB;
795 796 797
		/* Guess KDE menus */
		if(g_file_exists(KDE_MENUDIR))
				  flags |= MAIN_MENU_KDE|MAIN_MENU_KDE_SUB;
798
		load_menu_applet ((char *)selection_data->data,flags,
799 800 801 802
				  panel, pos);
		break;
	}
	case TARGET_APPLET: {
803
		char *goad_id = (char *)selection_data->data;
804 805
		if(!goad_id)
			return;
806
		load_extern_applet(goad_id,NULL,panel,pos,FALSE);
807 808
		break;
	}
809 810 811 812 813 814 815 816 817 818
	case TARGET_APPLET_INTERNAL: {
		char *applet_type = (char *)selection_data->data;
		if(!applet_type)
			return;
		if(strcmp(applet_type,"MENU:MAIN")==0) {
			int flags = MAIN_MENU_SYSTEM|MAIN_MENU_USER;

			/*guess redhat menus*/
			if(g_file_exists("/etc/X11/wmconfig"))
				flags |= MAIN_MENU_REDHAT|MAIN_MENU_REDHAT_SUB;
819 820 821
			/* Guess KDE menus */
			if(g_file_exists(KDE_MENUDIR))
				flags |= MAIN_MENU_KDE|MAIN_MENU_KDE_SUB;
822 823 824 825 826 827

			load_menu_applet(NULL,flags, panel, pos);
		} else if(strcmp(applet_type,"DRAWER:NEW")==0) {
			load_drawer_applet(-1,NULL,NULL, panel, pos);
		} else if(strcmp(applet_type,"LOGOUT:NEW")==0) {
			load_logout_applet(panel, pos);
828 829
		} else if(strcmp(applet_type,"LOCK:NEW")==0) {
			load_lock_applet(panel, pos);
830 831 832 833
		} else if(strcmp(applet_type,"SWALLOW:ASK")==0) {
			ask_about_swallowing(panel,pos);
		} else if(strcmp(applet_type,"LAUNCHER:ASK")==0) {
			ask_about_launcher(NULL,panel,pos);
834 835
		} else if(strcmp(applet_type,"STATUS:TRY")==0) {
			load_status_applet(panel,pos);
836 837 838
		}
		break;
	}
839 840
	}
}
841

842 843
static void
panel_widget_setup(PanelWidget *panel)
844
{
845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860
	gtk_signal_connect(GTK_OBJECT(panel),
			   "applet_added",
			   GTK_SIGNAL_FUNC(panel_applet_added),
			   NULL);
	gtk_signal_connect(GTK_OBJECT(panel),
			   "applet_removed",
			   GTK_SIGNAL_FUNC(panel_applet_removed),
			   NULL);
	gtk_signal_connect(GTK_OBJECT(panel),
			   "applet_move",
			   GTK_SIGNAL_FUNC(panel_applet_move),
			   NULL);
	gtk_signal_connect(GTK_OBJECT(panel),
			   "back_change",
			   GTK_SIGNAL_FUNC(panel_back_change),
			   NULL);
Owen Taylor's avatar
Owen Taylor committed
861
	gtk_signal_connect(GTK_OBJECT(panel),
862 863
			   "size_change",
			   GTK_SIGNAL_FUNC(panel_size_change),
Owen Taylor's avatar
Owen Taylor committed
864
			   NULL);
865 866 867 868
	gtk_signal_connect (GTK_OBJECT (panel),
			    "orient_change",
			    GTK_SIGNAL_FUNC (panel_orient_change),
			    NULL);
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
void
basep_pos_connect_signals (BasePWidget *basep)
{
	if (IS_BORDER_WIDGET (basep)) {
		gtk_signal_connect (GTK_OBJECT (basep->pos),
				    "edge_change",
				    GTK_SIGNAL_FUNC (border_edge_change),
				    basep);
	}

	if (IS_ALIGNED_WIDGET (basep))
		gtk_signal_connect (GTK_OBJECT (basep->pos),
				    "align_change",
				    GTK_SIGNAL_FUNC (aligned_align_change),
				    basep);
	else if (IS_SLIDING_WIDGET (basep)) {
		gtk_signal_connect (GTK_OBJECT (basep->pos),
				    "anchor_change",
				    GTK_SIGNAL_FUNC (sliding_anchor_change),
				    basep);
		gtk_signal_connect (GTK_OBJECT (basep->pos),
				    "offset_change",
				    GTK_SIGNAL_FUNC (sliding_offset_change),
				    basep);
	}
}
897

898 899
void
panel_setup(GtkWidget *panelw)
Elliot Lee's avatar
Elliot Lee committed
900
{
901
	PanelData *pd;
902 903 904 905 906 907
	BasePWidget *basep; 
	PanelWidget *panel;

	g_return_if_fail(panelw);

	basep = BASEP_WIDGET(panelw);
908
	panel = PANEL_WIDGET(basep->panel);
909

910
	pd = g_new(PanelData,1);
911 912
	pd->menu = NULL;
	pd->menu_age = 0;
913
	pd->panel = panelw;
914

915 916 917
	if (IS_BASEP_WIDGET (panelw) &&
	    !IS_DRAWER_WIDGET (panelw))
		base_panels++;
918 919 920 921
	
	if(IS_EDGE_WIDGET(panelw))
		pd->type = EDGE_PANEL;
	else if(IS_DRAWER_WIDGET(panelw))
922
		pd->type = DRAWER_PANEL;
923 924 925 926
	else if(IS_ALIGNED_WIDGET(panelw))
		pd->type = ALIGNED_PANEL;
	else if(IS_SLIDING_WIDGET(panelw))
		pd->type = SLIDING_PANEL;
927 928 929
	else if(IS_FLOATING_WIDGET(panelw))
		pd->type = FLOATING_PANEL;
	else
930 931
		g_warning("unknown panel type");
	
932
	panel_list = g_slist_append(panel_list,pd);
933 934 935
	
	gtk_object_set_user_data(GTK_OBJECT(panelw),pd);

936 937 938 939 940 941 942 943 944 945 946 947 948
	gtk_signal_connect(GTK_OBJECT(basep->hidebutton_e), "event",
			   (GtkSignalFunc) panel_sub_event_handler,
			   panelw);
	gtk_signal_connect(GTK_OBJECT(basep->hidebutton_w), "event",
			   (GtkSignalFunc) panel_sub_event_handler,
			   panelw);
	gtk_signal_connect(GTK_OBJECT(basep->hidebutton_n), "event",
			   (GtkSignalFunc) panel_sub_event_handler,
			   panelw);
	gtk_signal_connect(GTK_OBJECT(basep->hidebutton_s), "event",
			   (GtkSignalFunc) panel_sub_event_handler,
			   panelw);

949 950
	panel_widget_setup(panel);

951 952 953
	gtk_signal_connect(GTK_OBJECT(basep),
			   "drag_data_received",
			   GTK_SIGNAL_FUNC(panel_widget_dnd_drop_internal),
954
			   NULL);
955 956 957 958 959 960 961 962

	gtk_drag_dest_set (GTK_WIDGET (basep),
			   GTK_DEST_DEFAULT_MOTION |
			   GTK_DEST_DEFAULT_HIGHLIGHT |
			   GTK_DEST_DEFAULT_DROP,
			   panel_drop_types, n_panel_drop_types,
			   GDK_ACTION_COPY);

963 964 965 966 967 968
	gtk_signal_connect (GTK_OBJECT (basep),
			    "state_change",
			    GTK_SIGNAL_FUNC (basep_state_change),
			    NULL);

	basep_pos_connect_signals (basep);
969

970
	basep_widget_disable_buttons(basep);
971 972
	gtk_signal_connect(GTK_OBJECT(panelw), "event",
			   GTK_SIGNAL_FUNC(panel_event),pd);
973 974 975 976
	
	gtk_widget_set_events(panelw,
			      gtk_widget_get_events(panelw) |
			      PANEL_EVENT_MASK);
977
 
978 979
	gtk_signal_connect(GTK_OBJECT(panelw), "destroy",
			   GTK_SIGNAL_FUNC(panel_destroy),NULL);
980 981 982 983 984 985 986 987 988


	if(GTK_WIDGET_REALIZED(GTK_WIDGET(panelw)))
		panel_realize(GTK_WIDGET(panelw),NULL);
	else
		gtk_signal_connect_after(GTK_OBJECT(panelw), "realize",
					 GTK_SIGNAL_FUNC(panel_realize),
					 NULL);
}
989

990 991 992 993
/*send state change to all the panels*/
void
send_state_change(void)
{
994 995
	GSList *list;
	for(list = panel_list; list != NULL; list = g_slist_next(list)) {
996
		PanelData *pd = list->data;
997 998 999 1000
		if(!IS_DRAWER_WIDGET(pd->panel))
			basep_state_change(pd->panel,
					   BASEP_WIDGET(pd->panel)->state,
					   NULL);
1001
	}
Elliot Lee's avatar
Elliot Lee committed
1002
}
1003