applet-lib.cc 13.2 KB
Newer Older
1
#include <config.h>
2 3
#include <mico/gtkmico.h>
#include <mico/naming.h>
4
#include <fcntl.h>
5 6 7 8 9
#include <gnome.h>
#include <gdk/gdkx.h>
#include "panel.h"
#include "gnome-panel.h"
#include "applet-lib.h"
10
#include "applet-widget.h"
11
#include "panel-widget.h"
12
#include "mico-parse.h"
13 14 15 16 17 18 19 20 21 22 23 24

/*
 *
 * there is a lot of functionality in this file that is then slightly
 * redundant in the applet-widget ... this is because I wish to keep
 * applet-widget a clean C file, while applet-lib as the corba interface
 * after we have a C orb, we can do everything in applet-widget
 *
 */



25
#include "cookie.h"
26

27 28 29 30 31
#define APPLET_EVENT_MASK (GDK_BUTTON_PRESS_MASK |		\
			   GDK_BUTTON_RELEASE_MASK |		\
			   GDK_POINTER_MOTION_MASK |		\
			   GDK_POINTER_MOTION_HINT_MASK)

32 33
GNOME::Panel_var panel_client;

34 35
typedef struct _CallbackInfo CallbackInfo;
struct _CallbackInfo {
36
	char *name;
George Lebl's avatar
George Lebl committed
37
	int applet_id;
38 39 40 41
	AppletCallbackFunc func;
	gpointer data;
};

42
GList *applet_callbacks = NULL;
43 44 45 46

#define APPLET_ID_KEY "applet_id_key"
#define APPLET_WIDGET_KEY "applet_widget_key"

47
CORBA::ORB_ptr orb_ptr;
48
CORBA::BOA_ptr boa_ptr;
49

50 51
char *cookie;

52
BEGIN_GNOME_DECLS
53

54 55 56
void _gnome_applet_change_orient(int applet_id, int orient);
int _gnome_applet_session_save(int applet_id, const char *cfgpath,
			       const char *globcfgpath);
57
int _gnome_applet_start_new_applet(const char *params);
58 59 60
void _gnome_applet_back_change(int applet_id, int back_type,
			       const char *pixmap, GdkColor *color);
void _gnome_applet_tooltips_state(int enabled);
61

62 63 64 65
END_GNOME_DECLS

class Applet_impl : virtual public GNOME::Applet_skel {
public:
66 67
	void change_orient (const char *ccookie, CORBA::Short applet_id,
			    CORBA::Short orient) {
68
		CHECK_COOKIE ();
69
		::_gnome_applet_change_orient(applet_id,orient);
70
	}
71 72
	CORBA::Short session_save (const char *ccookie,
				   CORBA::Short applet_id,
73 74
			   	   const char *cfgpath,
			   	   const char *globcfgpath) {
75
		CHECK_COOKIE_V (0);
76 77
		return ::_gnome_applet_session_save(applet_id,cfgpath,
						    globcfgpath);
78
	}
79 80
        void do_callback (const char *ccookie,
			  CORBA::Short applet_id,
81 82
			  const char *callback_name)
        {
83 84
		GList *list;

85
		CHECK_COOKIE ();
86

87 88
		for(list = applet_callbacks;
		    list!=NULL;list = (GList *) g_list_next (list)) {
89
			CallbackInfo *info = (CallbackInfo *)list->data;
90 91 92 93 94
			if(info->applet_id == applet_id &&
			   strcmp(info->name,(char *)callback_name)==0) {
				(*(info->func)) (
					applet_widget_get_by_id(applet_id),
					info->data);
95
				return;
96 97
			}
		}
98
	}
99
	void start_new_applet (const char *ccookie,
100
			       const char *param)
101 102
	{
		CHECK_COOKIE ();
103
		::_gnome_applet_start_new_applet(param);
104
	}
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
	void back_change (const char *ccookie,
			  CORBA::Short applet_id,
			  CORBA::Short back_type,
			  const char *pixmap,
			  CORBA::Short c_red,
			  CORBA::Short c_green,
			  CORBA::Short c_blue)
	{
		GdkColor color;
		CHECK_COOKIE ();
		
		color.pixel = 1;
		color.red = c_red;
		color.green = c_green;
		color.blue = c_blue;

		::_gnome_applet_back_change(applet_id,back_type,
					    pixmap, &color);
	}
	void tooltips_state (const char *ccookie,
			     CORBA::Short enabled)
	{
		CHECK_COOKIE ();
		::_gnome_applet_tooltips_state(enabled);
	}
130 131 132
};

int
133
gnome_panel_applet_init_corba (void)
134 135 136 137
{
	char *name;
	char *iior;
	char hostname [1024];
138
	char buf[256];
139
	int i;
140 141 142 143 144
	
	gethostname (hostname, sizeof (hostname));
	if (hostname [0] == 0)
		strcpy (hostname, "unknown-host");

145 146 147 148
	/*do a 20 second timeout until we get the iior*/
	for(i=0;i<20;i++) {
		name = g_copy_strings ("/CORBA-servers/Panel-", hostname, 
				       "/DISPLAY-", getenv ("DISPLAY"), NULL);
149

150 151 152 153 154 155 156 157
		iior = gnome_config_get_string (name);
		g_free (name);

		if(iior)
			break;
		sleep(1);
	}
	if(!iior)
158
		return 0;
Tom Tromey's avatar
Tom Tromey committed
159

160 161 162 163
	g_snprintf(buf,256,"/panel/Secret/cookie-DISPLAY-%s=",
		   getenv("DISPLAY"));
	cookie = gnome_config_private_get_string (buf);

164

165
	panel_initialize_corba (&orb_ptr, &boa_ptr);
Tom Tromey's avatar
Tom Tromey committed
166

167 168 169 170 171 172 173 174
	orb_ptr->dispatcher (new GtkDispatcher ());

	CORBA::Object_var obj = orb_ptr->string_to_object (iior);
	
	panel_client = GNOME::Panel::_narrow (obj);
	return 1;
}

175 176 177 178 179 180 181
/*reread the panel's address*/
int
gnome_panel_applet_reinit_corba (void)
{
	char *name;
	char *iior;
	char hostname [1024];
182
	char buf[256];
183
	int i;
184 185 186 187 188
	
	gethostname (hostname, sizeof (hostname));
	if (hostname [0] == 0)
		strcpy (hostname, "unknown-host");

189 190 191 192
	/*do a 20 second timeout until we get the iior*/
	for(i=0;i<20;i++) {
		name = g_copy_strings ("/CORBA-servers/Panel-", hostname, 
				       "/DISPLAY-", getenv ("DISPLAY"), NULL);
193

194 195 196 197 198 199 200 201
		iior = gnome_config_get_string (name);
		g_free (name);

		if(iior)
			break;
		sleep(1);
	}
	if(!iior)
202 203
		return 0;

204 205 206
	g_snprintf(buf,256,"/panel/Secret/cookie-DISPLAY-%s=",
		   getenv("DISPLAY"));
	cookie = gnome_config_private_get_string (buf);
207

208 209 210 211 212 213
	CORBA::Object_var obj = orb_ptr->string_to_object (iior);
	
	panel_client = GNOME::Panel::_narrow (obj);
	return 1;
}

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
214
static CallbackInfo *
George Lebl's avatar
George Lebl committed
215
get_callback_info(int applet_id, char *name)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
216 217 218 219
{
	GList *list;
	for(list=applet_callbacks;list!=NULL;list=g_list_next(list)) {
		CallbackInfo *info = (CallbackInfo *)list->data;
220
		if(applet_id == info->applet_id && strcmp(name,info->name)==0)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
221 222 223 224 225
			return info;
	}
	return NULL;
}

George Lebl's avatar
George Lebl committed
226 227
static char*
make_sane_name(char *name)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
228 229 230 231 232 233 234 235 236 237
{
	if(!name)
		return NULL;
	while(*name=='/')
		name++;
	if(*name)
		return name;
	return NULL;
}

238
/*adds a callback to the callback hash*/
239
void
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
240
gnome_panel_applet_register_callback(int applet_id,
241
				     char *name,
242
				     char *stock_item,
243
				     char *menutext,
244
				     AppletCallbackFunc func,
245 246
				     gpointer data)
{
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
247 248 249 250 251 252
	CallbackInfo *info;
	/*skip over leading '/'s*/
	name = make_sane_name(name);

	g_return_if_fail(name!=NULL);
	
253
	info = get_callback_info(applet_id,name);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
254 255 256 257 258
	if(!info) {
		info = g_new(CallbackInfo,1);
		applet_callbacks = g_list_prepend(applet_callbacks,info);
	} else
		g_free(info->name);
259

260
	info->name = g_strdup(name);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
261
	info->applet_id = applet_id;
262 263 264
	info->func = func;
	info->data = data;

265
	/*register the callback with the panel*/
266 267
	panel_client->applet_add_callback(cookie,applet_id,name,
					  stock_item,menutext);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286
}

/*removes a callback from the callback hash*/
void
gnome_panel_applet_unregister_callback(int applet_id,
				       char *name)
{
	/*skip over leading '/'s*/
	name = make_sane_name(name);

	g_return_if_fail(name!=NULL);

	/*unregister the callback with the panel*/
	panel_client->applet_remove_callback(cookie,applet_id,name);
}

void
gnome_panel_applet_register_callback_dir(int applet_id,
					 char *name,
287
					 char *stock_item,
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
288 289
					 char *menutext)
{
George Lebl's avatar
George Lebl committed
290
	char *n;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
291 292 293 294 295 296 297 298 299
	/*skip over leading '/'s*/
	name = make_sane_name(name);
	g_return_if_fail(name!=NULL);

	if(name[strlen(name)-1]!='/')
		n = g_copy_strings(name,"/",NULL);
	else
		n = g_strdup(name);
	/*unregister the dir with the panel*/
300
	panel_client->applet_add_callback(cookie,applet_id,n,stock_item,menutext);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
301 302 303 304 305 306 307 308
	g_free(n);
}

/*removes a callback dir from the callback menu*/
void
gnome_panel_applet_unregister_callback_dir(int applet_id,
					   char *name)
{
George Lebl's avatar
George Lebl committed
309
	char *n;
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
310 311 312 313 314 315 316 317 318 319 320 321 322

	/*skip over leading '/'s*/
	name = make_sane_name(name);
	if(name[strlen(name)-1]!='/')
		n = g_copy_strings(name,"/",NULL);
	else
		n = g_strdup(name);

	g_return_if_fail(name!=NULL);

	/*unregister the callback with the panel*/
	panel_client->applet_remove_callback(cookie,applet_id,n);
	g_free(n);
323 324
}

325
/*catch events relevant to the panel and notify the panel*/
George Lebl's avatar
George Lebl committed
326
static int
327 328
applet_event(GtkWidget *widget, GdkEvent *event, gpointer data)
{
329
	int ourid = GPOINTER_TO_INT(data);
330
	GdkEventButton *bevent;
George Lebl's avatar
George Lebl committed
331
	int in_drag;
332 333 334 335

	switch (event->type) {
		case GDK_BUTTON_PRESS:
			bevent = (GdkEventButton *) event;
336 337 338 339 340
			in_drag = panel_client->applet_in_drag(cookie);
			/*check to see if there is an applet being dragged*/
			if(bevent->button == 2 && !in_drag) {
				gdk_pointer_ungrab(GDK_CURRENT_TIME);
				gtk_grab_remove(widget);
341
				panel_client->applet_drag_start(cookie,ourid);
342
				return TRUE;
343
			} else if(in_drag) {
344
				panel_client->applet_drag_stop(cookie,ourid);
345
				return TRUE;
346
			} else if(bevent->button == 3 && !in_drag) {
347 348
				gdk_pointer_ungrab(GDK_CURRENT_TIME);
				gtk_grab_remove(widget);
349
				panel_client->applet_show_menu(cookie, ourid);
350 351 352 353
				return TRUE;
			}
			break;
		case GDK_BUTTON_RELEASE:
354
			if(panel_client->applet_in_drag(cookie)) {
355
				panel_client->applet_drag_stop(cookie, ourid);
356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
				return TRUE;
			}
			break;
		default:
			break;
	}

	return FALSE;
}

static GtkWidget *
listening_parent(GtkWidget *widget)
{
	if (GTK_WIDGET_NO_WINDOW(widget))
		return listening_parent(widget->parent);

	return widget;
}

George Lebl's avatar
George Lebl committed
375
static int
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409
applet_sub_event_handler(GtkWidget *widget, GdkEvent *event, gpointer data)
{
	switch (event->type) {
		/*pass these to the parent!*/
		case GDK_BUTTON_PRESS:
		case GDK_BUTTON_RELEASE:
			return gtk_widget_event(
				listening_parent(widget->parent), event);

			break;

		default:
			break;
	}

	return FALSE;
}


static void
bind_applet_events(GtkWidget *widget, gpointer data)
{
	if (!GTK_WIDGET_NO_WINDOW(widget)) {
		gtk_signal_connect(GTK_OBJECT(widget), "event",
				   (GtkSignalFunc) applet_sub_event_handler,
				   NULL);
	}
	
	if (GTK_IS_CONTAINER(widget))
		gtk_container_foreach (GTK_CONTAINER (widget),
				       bind_applet_events, NULL);
}

static void
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
410
bind_top_applet_events(GtkWidget *widget, int applet_id)
411 412 413 414
{
	gtk_signal_connect(GTK_OBJECT(widget),
			   "event",
			   GTK_SIGNAL_FUNC(applet_event),
415
			   GINT_TO_POINTER(applet_id));
416 417 418 419 420 421 422 423 424

	if (GTK_IS_CONTAINER(widget))
		gtk_container_foreach (GTK_CONTAINER (widget),
				       bind_applet_events, NULL);
}

/*id will return a unique id for this applet for the applet to identify
  itself as*/
char *
425 426
gnome_panel_applet_request_id (const char *path,
			       const char *param,
427
			       int dorestart,
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
428
			       int *applet_id,
429
			       char **cfgpath,
430 431
			       char **globcfgpath,
			       guint32 *winid)
432 433
{
	char *result;
434 435
	char *cfg = NULL;
	char *globcfg = NULL;
436
	CORBA::ULong wid;
437
	int i;
438

439 440
	/*this is the first call to panel so we'll do a loop and timeout
	  after 20 seconds if we don't find a panel*/
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
441
	*applet_id = -1;
442 443 444 445

	for(i=0;i<20;i++) {
		try {
			/*reserve a spot and get an id for this applet*/
446
			*applet_id = panel_client->applet_request_id(cookie,
447 448
								     path,
								     param,
449
								     dorestart,
450
								     cfg,
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
451 452
							             globcfg,
								     wid);
453 454 455 456 457
		} catch (...) {
			sleep(1);
			gnome_panel_applet_reinit_corba ();
			continue;
		}
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
458
		if(*applet_id!=-1)
459
			break;
George Lebl's avatar
George Lebl committed
460
		sleep(1);
461 462
	}
	/*if the request_id never completed*/
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
463
	if(*applet_id == -1)
464
		return g_strdup("Can't talk to a panel\n");
465 466 467

	if(winid)
		*winid = wid;
468 469

	if(cfgpath==NULL) {
470 471 472 473
		CORBA::string_free(cfg);
	} else if(cfg != NULL) {
		*cfgpath = g_strdup(cfg);
		CORBA::string_free(cfg);
474 475 476
	} else {
		*cfgpath = NULL;
	}
477
	if(globcfgpath==NULL) {
478 479 480 481
		CORBA::string_free(globcfg);
	} else if(globcfg != NULL) {
		*globcfgpath = g_strdup(globcfg);
		CORBA::string_free(globcfg);
482 483 484
	} else {
		*globcfgpath = NULL;
	}
485 486 487 488

	return 0;
}

489 490 491

/*this function will register the ior with the panel so it can call us*/
char *
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
492
gnome_panel_applet_register (GtkWidget *widget, int applet_id)
493 494
{
	char *result;
495 496 497 498
	static char *ior=NULL;

	/*the applet implementation, it's only created once*/
	static GNOME::Applet_ptr applet = new Applet_impl ();
499 500 501 502 503 504

	/* Now a way to find out the CORBA impl from the widget */
	gtk_object_set_data (GTK_OBJECT (widget), "CORBA_object", applet);

	ior = orb_ptr->object_to_string (applet);

505
	panel_client->applet_register(cookie, ior,applet_id);
506

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
507
	bind_top_applet_events(widget,applet_id);
508 509 510 511

	return 0;
}

512
char *
George Lebl's avatar
George Lebl committed
513
gnome_panel_applet_abort_id (int applet_id)
514
{
515
	panel_client->applet_abort_id(cookie, applet_id);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
516 517 518 519

	return 0;
}

George Lebl's avatar
George Lebl committed
520 521
int
gnome_panel_applet_get_panel_orient (int applet_id)
522 523 524 525
{
	return panel_client->applet_get_panel_orient(cookie, applet_id);
}

526
char *
George Lebl's avatar
George Lebl committed
527
gnome_panel_applet_remove_from_panel (int applet_id)
528 529 530 531 532 533
{
	panel_client->applet_remove_from_panel(cookie, applet_id);

	return 0;
}

Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
534
char *
George Lebl's avatar
George Lebl committed
535
gnome_panel_applet_add_tooltip (int applet_id, char *tooltip)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
536
{
537
	panel_client->applet_add_tooltip(cookie, applet_id,tooltip);
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
538 539 540 541 542

	return 0;
}

char *
George Lebl's avatar
George Lebl committed
543
gnome_panel_applet_remove_tooltip (int applet_id)
Jiri (George) Lebl's avatar
Jiri (George) Lebl committed
544
{
545
	panel_client->applet_remove_tooltip(cookie, applet_id);
546 547 548 549 550 551 552 553 554 555 556 557 558

	return 0;
}

/*id will return a unique id for this applet for the applet to identify
  itself as*/
char *
gnome_panel_applet_request_glob_cfg (char **globcfgpath)
{
	char *globcfg = NULL;

	g_return_val_if_fail(globcfgpath!=NULL,0);

Arturo Espinosa's avatar
Arturo Espinosa committed
559
	panel_client->applet_request_glob_cfg(cookie, globcfg);
560 561 562 563 564 565 566 567 568 569 570

	if(globcfg!= NULL) {
		*globcfgpath = g_strdup(globcfg);
		CORBA::string_free(globcfg);
	} else {
		*globcfgpath = NULL;
	}

	return 0;
}

571
void
George Lebl's avatar
George Lebl committed
572
gnome_panel_applet_cleanup(int applet_id)
573 574 575 576 577 578 579 580 581 582
{
	GList *list;
	GList *nlist;

	for(list = applet_callbacks;list!=NULL;) {
		CallbackInfo *info = (CallbackInfo *)list->data;
		nlist = g_list_next(list);
		if(info->applet_id == applet_id) {
			g_free(info->name);
			g_list_remove_link(applet_callbacks,list);
583
			g_list_free(list);
584 585 586 587 588 589
			g_free(info);
		}
		list = nlist;
	}
}

590

591
char *
592
gnome_panel_sync_config (int applet_id)
593 594 595
{
	char *result;

596
	panel_client->sync_config (cookie,applet_id);
597 598 599 600

	return 0;
}

601 602 603 604 605
char *
gnome_panel_quit (void)
{
	char *result;

606
	panel_client->quit (cookie);
607 608 609

	return 0;
}
610

611 612 613 614
void
applet_corba_gtk_main (char *str)
{
	boa_ptr->impl_is_ready (CORBA::ImplementationDef::_nil());
615 616 617
#ifdef HAVE_MICO_ORB_RUN       
	orb_ptr->run ();
#endif	
618
}
619 620 621 622 623 624

void
applet_corba_gtk_main_quit (void)
{
	boa_ptr->deactivate_impl (CORBA::ImplementationDef::_nil());
#ifdef HAVE_MICO_ORB_RUN       
625
	orb_ptr->shutdown (TRUE);
626 627
#endif	
}