Remove src/plugins/pager.c
[lxde/lxpanel.git] / src / plugins / wnckpager.c
1 /* pager.c -- pager module of lxpanel project
2 *
3 * Copyright (C) 2002-2003 Anatoly Asviyan <aanatoly@users.sf.net>
4 * Joe MacDonald <joe@deserted.net>
5 *
6 * This file is part of lxpanel.
7 *
8 * lxpanel is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2, or (at your option)
11 * any later version.
12 *
13 * lxpanel is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with sawfish; see the file COPYING. If not, write to
20 * the Free Software Foundation, 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301 USA.
22 */
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <string.h>
26 #include <stdlib.h>
27 #include <gtk/gtk.h>
28
29 #include <X11/Xlib.h>
30 #include <X11/Xutil.h>
31
32 #include <gdk-pixbuf/gdk-pixbuf.h>
33 #include <glib/gi18n.h>
34 #ifndef WNCK_I_KNOW_THIS_IS_UNSTABLE
35 #define WNCK_I_KNOW_THIS_IS_UNSTABLE
36 #endif
37 #include <libwnck/libwnck.h>
38
39 #include "panel.h"
40 #include "misc.h"
41 #include "private.h"
42
43 #include "dbg.h"
44
45 #if 0
46 /* managed window: all related info that wm holds about its managed windows */
47 typedef struct task {
48 Window win;
49 int x, y;
50 guint w, h;
51 gint refcount;
52 guint stacking;
53 guint desktop;
54 char *name, *iname;
55 int ws;
56 NetWMState nws;
57 NetWMWindowType nwwt;
58 guint focused:1;
59 } task;
60
61 typedef struct _desk desk;
62 typedef struct _pager pager;
63
64 #define MAX_DESK_NUM 20
65 /* map of a desktop */
66 struct _desk {
67 GtkWidget *da;
68 GdkPixmap *pix;
69 int no, dirty, first;
70 gfloat scalew, scaleh;
71 pager *pg;
72 };
73 #endif
74
75 typedef struct _pager {
76 Plugin* plugin;
77 GtkWidget *box;
78 // GtkWidget *eb;
79 // desk *desks[MAX_DESK_NUM];
80 // guint desknum;
81 // guint curdesk;
82 // int dw, dh;
83 // gfloat scalex, scaley, ratio;
84 // Window *wins;
85 // int winnum, dirty;
86 // GHashTable* htable;
87 // task *focusedtask;
88 } pager;
89
90
91 #define TASK_VISIBLE(tk) \
92 (!( (tk)->nws.hidden || (tk)->nws.skip_pager ))
93 //if (t->nws.skip_pager || t->nwwt.desktop /*|| t->nwwt.dock || t->nwwt.splash*/ )
94
95 //static void pager_rebuild_all(FbEv *ev, pager *pg);
96
97 //static inline void desk_set_dirty_by_win(pager *p, task *t);
98 //static inline void desk_set_dirty(desk *d);
99 //static inline void desk_set_dirty_all(pager *pg);
100 /*
101 static void desk_clear_pixmap(desk *d);
102 static gboolean task_remove_stale(Window *win, task *t, pager *p);
103 static gboolean task_remove_all(Window *win, task *t, pager *p);
104 */
105
106
107
108
109 /*****************************************************************
110 * Task Management Routines *
111 *****************************************************************/
112
113 #if 0
114 /* tell to remove element with zero refcount */
115 static gboolean
116 task_remove_stale(Window *win, task *t, pager *p)
117 {
118 if (t->refcount-- == 0) {
119 desk_set_dirty_by_win(p, t);
120 if (p->focusedtask == t)
121 p->focusedtask = NULL;
122 DBG("del %x\n", t->win);
123 g_free(t);
124 return TRUE;
125 }
126 return FALSE;
127 }
128
129 /* tell to remove element with zero refcount */
130 static gboolean
131 task_remove_all(Window *win, task *t, pager *p)
132 {
133 g_free(t);
134 return TRUE;
135 }
136
137
138 static void
139 task_get_sizepos(task *t)
140 {
141 Window root, junkwin;
142 int rx, ry;
143 guint dummy;
144 XWindowAttributes win_attributes;
145
146 ENTER;
147 if (!XGetWindowAttributes(GDK_DISPLAY(), t->win, &win_attributes)) {
148 if (!XGetGeometry (GDK_DISPLAY(), t->win, &root, &t->x, &t->y, &t->w, &t->h,
149 &dummy, &dummy)) {
150 t->x = t->y = t->w = t->h = 2;
151 }
152
153 } else {
154 XTranslateCoordinates (GDK_DISPLAY(), t->win, win_attributes.root,
155 -win_attributes.border_width,
156 -win_attributes.border_width,
157 &rx, &ry, &junkwin);
158 t->x = rx;
159 t->y = ry;
160 t->w = win_attributes.width;
161 t->h = win_attributes.height;
162 DBG("win=0x%x WxH=%dx%d\n", t->win,t->w, t->h);
163 }
164 RET();
165 }
166
167
168 static void
169 task_update_pix(task *t, desk *d)
170 {
171 int x, y, w, h;
172 GtkWidget *widget;
173 Panel* p;
174
175 ENTER;
176 g_return_if_fail(d->pix != NULL);
177 if (!TASK_VISIBLE(t))
178 RET();;
179
180 p = d->pg->plugin->panel;
181 if (t->desktop < p->desknum &&
182 t->desktop != d->no)
183 RET();
184
185 x = (gfloat)t->x * d->scalew;
186 y = (gfloat)t->y * d->scaleh;
187 w = (gfloat)t->w * d->scalew;
188 //h = (gfloat)t->h * d->scaleh;
189 h = (t->nws.shaded) ? 3 : (gfloat)t->h * d->scaleh;
190 if (w < 3 || h < 3)
191 RET();
192 widget = GTK_WIDGET(d->da);
193 gdk_draw_rectangle (d->pix,
194 (d->pg->focusedtask == t) ?
195 widget->style->bg_gc[GTK_STATE_SELECTED] :
196 widget->style->bg_gc[GTK_STATE_NORMAL],
197 TRUE,
198 x+1, y+1, w-1, h-1);
199 gdk_draw_rectangle (d->pix,
200 (d->pg->focusedtask == t) ?
201 widget->style->fg_gc[GTK_STATE_SELECTED] :
202 widget->style->fg_gc[GTK_STATE_NORMAL],
203 FALSE,
204 x, y, w, h);
205 RET();
206 }
207
208
209 /*****************************************************************
210 * Desk Functions *
211 *****************************************************************/
212 static void
213 desk_clear_pixmap(desk *d)
214 {
215 GtkWidget *widget;
216
217 ENTER;
218 DBG("d->no=%d\n", d->no);
219 if (!d->pix)
220 RET();
221 widget = GTK_WIDGET(d->da);
222 gdk_draw_rectangle (d->pix,
223 ((d->no == d->pg->curdesk) ?
224 widget->style->dark_gc[GTK_STATE_SELECTED] :
225 widget->style->dark_gc[GTK_STATE_NORMAL]),
226 TRUE,
227 0, 0,
228 widget->allocation.width,
229 widget->allocation.height);
230
231 RET();
232 }
233
234
235
236 static inline void
237 desk_set_dirty(desk *d)
238 {
239 ENTER;
240 d->dirty = 1;
241 gtk_widget_queue_draw(d->da);
242 RET();
243 }
244
245 static inline void
246 desk_set_dirty_all(pager *pg)
247 {
248 int i;
249 ENTER;
250 for (i = 0; i < pg->desknum; i++)
251 desk_set_dirty(pg->desks[i]);
252 RET();
253 }
254
255 static inline void
256 desk_set_dirty_by_win(pager *p, task *t)
257 {
258 ENTER;
259 if (t->nws.skip_pager || t->nwwt.desktop /*|| t->nwwt.dock || t->nwwt.splash*/ )
260 RET();
261 if (t->desktop < p->desknum)
262 desk_set_dirty(p->desks[t->desktop]);
263 else
264 desk_set_dirty_all(p);
265 RET();
266 }
267
268 /* Redraw the screen from the backing pixmap */
269 static gint
270 desk_expose_event (GtkWidget *widget, GdkEventExpose *event, desk *d)
271 {
272 ENTER;
273 DBG("d->no=%d\n", d->no);
274
275 if (d->dirty) {
276 pager *pg = d->pg;
277 task *t;
278 int j;
279
280 d->dirty = 0;
281 desk_clear_pixmap(d);
282 for (j = 0; j < pg->winnum; j++) {
283 if (!(t = g_hash_table_lookup(pg->htable, &pg->wins[j])))
284 continue;
285 task_update_pix(t, d);
286 }
287 }
288 gdk_draw_drawable(widget->window,
289 widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
290 d->pix,
291 event->area.x, event->area.y,
292 event->area.x, event->area.y,
293 event->area.width, event->area.height);
294 RET(FALSE);
295 }
296
297 /* Upon realize and every resize creates a new backing pixmap of the appropriate size */
298 static gint
299 desk_configure_event (GtkWidget *widget, GdkEventConfigure *event, desk *d)
300 {
301 Panel* p;
302 int w, h;
303 ENTER;
304 DBG("d->no=%d %dx%d\n", d->no, widget->allocation.width, widget->allocation.height);
305 if (d->pix)
306 g_object_unref(d->pix);
307
308 d->pix = gdk_pixmap_new(widget->window,
309 widget->allocation.width,
310 widget->allocation.height,
311 -1);
312
313 d->scalew = (gfloat)widget->allocation.height / (gfloat)gdk_screen_height();
314 d->scaleh = (gfloat)widget->allocation.width / (gfloat)gdk_screen_width();
315 desk_set_dirty(d);
316
317 p = d->pg->plugin->panel;
318 //request best size
319 if (p->orientation != GTK_ORIENTATION_HORIZONTAL) {
320 w = widget->allocation.width;
321 h = (gfloat) w / d->pg->ratio;
322 } else {
323 h = widget->allocation.height;
324 w = (gfloat) h * d->pg->ratio;
325 }
326 DBG("requesting %dx%d\n", w, h);
327 gtk_widget_set_size_request(widget, w, h);
328
329 RET(FALSE);
330 }
331
332 static gint
333 desk_button_press_event(GtkWidget * widget, GdkEventButton * event, desk *d)
334 {
335 ENTER;
336 if( event->button == 3 ) { /* right button */
337 GtkMenu* popup =(GtkMenu*) lxpanel_get_panel_menu
338 ( d->pg->plugin->panel, d->pg->plugin, FALSE );
339 gtk_menu_popup( popup, NULL, NULL, NULL, NULL, event->button, event->time );
340 return TRUE;
341 }
342
343 Xclimsg(GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, d->no, 0, 0, 0, 0);
344 RET(TRUE);
345 }
346
347 /*
348 static gint
349 desk_button_release_event(GtkWidget * widget, GdkEventButton * event, desk *d)
350 {
351 ENTER;
352 DBG("t=%d\n", d->no);
353 Xclimsg(GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, d->no, 0, 0, 0, 0);
354 RET(TRUE);
355 }
356 */
357
358 static gint
359 desk_scroll_event (GtkWidget *widget, GdkEventScroll *event, desk *d)
360 {
361 int i;
362
363 ENTER;
364 DBG("scroll direction = %d\n", event->direction);
365 i = d->pg->curdesk;
366 if (event->direction == GDK_SCROLL_UP ||event->direction == GDK_SCROLL_LEFT) {
367 i--;
368 if (i < 0)
369 i = d->pg->desknum - 1;
370 } else {
371 i++;
372 if (i >= d->pg->desknum)
373 i = 0;
374 }
375 Xclimsg(GDK_ROOT_WINDOW(), a_NET_CURRENT_DESKTOP, i, 0, 0, 0, 0);
376 RET(TRUE);
377 }
378
379 static void
380 desk_new(pager *pg, int i)
381 {
382 desk *d;
383
384 ENTER;
385 g_assert(i < pg->desknum);
386 d = pg->desks[i] = g_new0(desk, 1);
387 d->pg = pg;
388 d->pix = NULL;
389 d->dirty = 0;
390 d->first = 1;
391 d->no = i;
392
393 d->da = gtk_drawing_area_new();
394 //gtk_widget_set_size_request(GTK_WIDGET(d->da), 10, 10);
395 gtk_box_pack_start(GTK_BOX(pg->box), d->da, TRUE, TRUE, 0);
396 gtk_widget_add_events (d->da, GDK_EXPOSURE_MASK
397 | GDK_BUTTON_PRESS_MASK
398 | GDK_BUTTON_RELEASE_MASK);
399 g_signal_connect (G_OBJECT (d->da), "expose-event",
400 (GCallback) desk_expose_event, (gpointer)d);
401 g_signal_connect (G_OBJECT (d->da), "configure-event",
402 (GCallback) desk_configure_event, (gpointer)d);
403 g_signal_connect (G_OBJECT (d->da), "scroll-event",
404 (GCallback) desk_scroll_event, (gpointer)d);
405 g_signal_connect (G_OBJECT (d->da), "button-press-event",
406 (GCallback) desk_button_press_event, (gpointer)d);
407 //g_signal_connect (G_OBJECT (d->da), "button_release_event",
408 // (GCallback) desk_button_release_event, (gpointer)d);
409 gtk_widget_show(d->da);
410 DBG("before pack\n");
411
412 DBG("after show\n");
413 RET();
414 }
415
416 static void
417 desk_free(pager *pg, int i)
418 {
419 desk *d;
420
421 ENTER;
422 d = pg->desks[i];
423 DBG("i=%d d->no=%d d->da=%p d->pix=%p\n",
424 i, d->no, d->da, d->pix);
425 if (d->pix)
426 g_object_unref(d->pix);
427 gtk_widget_destroy(d->da);
428 g_free(d);
429 RET();
430 }
431
432
433 /*****************************************************************
434 * Netwm/WM Interclient Communication *
435 *****************************************************************/
436
437 static void
438 do_net_active_window(FbEv *ev, pager *p)
439 {
440 Window *fwin;
441 task *t;
442
443 ENTER;
444 fwin = get_xaproperty(GDK_ROOT_WINDOW(), a_NET_ACTIVE_WINDOW, XA_WINDOW, 0);
445 DBG("win=%x\n", fwin ? *fwin : 0);
446 if (fwin) {
447 t = g_hash_table_lookup(p->htable, fwin);
448 if (t != p->focusedtask) {
449 if (p->focusedtask)
450 desk_set_dirty_by_win(p, p->focusedtask);
451 p->focusedtask = t;
452 if (t)
453 desk_set_dirty_by_win(p, t);
454 }
455 XFree(fwin);
456 } else {
457 if (p->focusedtask) {
458 desk_set_dirty_by_win(p, p->focusedtask);
459 p->focusedtask = NULL;
460 }
461 }
462 RET();
463 }
464
465 static void
466 do_net_current_desktop(FbEv *ev, pager *p)
467 {
468 ENTER;
469 desk_set_dirty(p->desks[p->curdesk]);
470 p->curdesk = get_net_current_desktop ();
471 if (p->curdesk >= p->desknum)
472 p->curdesk = 0;
473 desk_set_dirty(p->desks[p->curdesk]);
474 RET();
475 }
476
477
478 static void
479 do_net_client_list_stacking(FbEv *ev, pager *p)
480 {
481 int i;
482 task *t;
483
484 ENTER;
485 if (p->wins)
486 XFree(p->wins);
487 p->wins = get_xaproperty (GDK_ROOT_WINDOW(), a_NET_CLIENT_LIST_STACKING,
488 XA_WINDOW, &p->winnum);
489 if (!p->wins || !p->winnum)
490 RET();
491
492 /* refresh existing tasks and add new */
493 for (i = 0; i < p->winnum; i++) {
494 if ((t = g_hash_table_lookup(p->htable, &p->wins[i]))) {
495 t->refcount++;
496 if (t->stacking != i) {
497 t->stacking = i;
498 desk_set_dirty_by_win(p, t);
499 }
500 } else {
501 t = g_new0(task, 1);
502 t->refcount++;
503 t->win = p->wins[i];
504 t->ws = get_wm_state (t->win);
505 t->desktop = get_net_wm_desktop(t->win);
506 get_net_wm_state(t->win, &t->nws);
507 get_net_wm_window_type(t->win, &t->nwwt);
508 task_get_sizepos(t);
509 if (!FBPANEL_WIN(t->win))
510 XSelectInput (GDK_DISPLAY(), t->win, PropertyChangeMask | StructureNotifyMask);
511 g_hash_table_insert(p->htable, &t->win, t);
512 DBG("add %x\n", t->win);
513 desk_set_dirty_by_win(p, t);
514 }
515 }
516 /* pass throu hash table and delete stale windows */
517 g_hash_table_foreach_remove(p->htable, (GHRFunc) task_remove_stale, (gpointer)p);
518 RET();
519 }
520
521
522 /*****************************************************************
523 * Pager Functions *
524 *****************************************************************/
525 /*
526 static void
527 pager_unmapnotify(pager *p, XEvent *ev)
528 {
529 Window win = ev->xunmap.window;
530 task *t;
531 if (!(t = g_hash_table_lookup(p->htable, &win)))
532 RET();
533 DBG("pager_unmapnotify: win=0x%x\n", win);
534 RET();
535 t->ws = WithdrawnState;
536 desk_set_dirty_by_win(p, t);
537 RET();
538 }
539 */
540 static void
541 pager_configurenotify(pager *p, XEvent *ev)
542 {
543 Window win = ev->xconfigure.window;
544 task *t;
545
546 ENTER;
547
548 if (!(t = g_hash_table_lookup(p->htable, &win)))
549 RET();
550 DBG("win=0x%x\n", win);
551 task_get_sizepos(t);
552 desk_set_dirty_by_win(p, t);
553 RET();
554 }
555
556 static void
557 pager_propertynotify(pager *p, XEvent *ev)
558 {
559 Atom at = ev->xproperty.atom;
560 Window win = ev->xproperty.window;
561 task *t;
562
563 ENTER;
564 if ((win == GDK_ROOT_WINDOW()) || !(t = g_hash_table_lookup(p->htable, &win)))
565 RET();
566
567 /* The property is deleted */
568 if( ((XPropertyEvent*)ev)->state == 1 )
569 return;
570
571 DBG("window=0x%x\n", t->win);
572 if (at == a_WM_STATE) {
573 DBG("event=WM_STATE\n");
574 t->ws = get_wm_state (t->win);
575 } else if (at == a_NET_WM_STATE) {
576 DBG("event=NET_WM_STATE\n");
577 get_net_wm_state(t->win, &t->nws);
578 } else if (at == a_NET_WM_DESKTOP) {
579 DBG("event=NET_WM_DESKTOP\n");
580 desk_set_dirty_by_win(p, t); // to clean up desks where this task was
581 t->desktop = get_net_wm_desktop(t->win);
582 } else {
583 RET();
584 }
585 desk_set_dirty_by_win(p, t);
586 RET();
587 }
588
589 static GdkFilterReturn
590 pager_event_filter( XEvent *xev, GdkEvent *event, pager *pg)
591 {
592 ENTER;
593 if (xev->type == PropertyNotify )
594 pager_propertynotify(pg, xev);
595 else if (xev->type == ConfigureNotify )
596 pager_configurenotify(pg, xev);
597 RET(GDK_FILTER_CONTINUE);
598 }
599
600
601
602
603
604 static void
605 pager_rebuild_all(FbEv *ev, pager *pg)
606 {
607 int desknum, dif, i;
608
609 ENTER;
610 desknum = pg->desknum;
611
612 pg->desknum = get_net_number_of_desktops();
613 if (pg->desknum < 1)
614 pg->desknum = 1;
615 else if (pg->desknum > MAX_DESK_NUM) {
616 pg->desknum = MAX_DESK_NUM;
617 ERR("pager: max number of supported desks is %d\n", MAX_DESK_NUM);
618 }
619 pg->curdesk = get_net_current_desktop();
620 if (pg->curdesk >= pg->desknum)
621 pg->curdesk = 0;
622 DBG("desknum=%d curdesk=%d\n", desknum, curdesk);
623 DBG("pg->desknum=%d pg->curdesk=%d\n", pg->desknum, pg->curdesk);
624 dif = pg->desknum - desknum;
625
626 if (dif == 0)
627 RET();
628
629 if (dif < 0) {
630 /* if desktops were deleted then delete their maps also */
631 for (i = pg->desknum; i < desknum; i++)
632 desk_free(pg, i);
633 } else {
634 for (i = desknum; i < pg->desknum; i++)
635 desk_new(pg, i);
636 }
637 do_net_client_list_stacking(NULL, pg);
638 RET();
639 }
640 #endif
641
642 static int
643 pager_wnck_constructor(Plugin *plug, char **fp)
644 {
645 pager *pg;
646
647 ENTER;
648 pg = g_new0(pager, 1);
649 g_return_val_if_fail(pg != NULL, 0);
650 plug->priv = pg;
651 pg->plugin = plug;
652
653 plug->pwid = gtk_event_box_new();
654 GTK_WIDGET_SET_FLAGS( plug->pwid, GTK_NO_WINDOW );
655
656 //pg->htable = g_hash_table_new (g_int_hash, g_int_equal);
657
658 pg->box = wnck_pager_new(NULL);
659 g_return_val_if_fail(pg->box != NULL, 0);
660 //set orientation
661 wnck_pager_set_orientation (WNCK_PAGER (pg->box),pg->plugin->panel->orientation);
662 wnck_pager_set_n_rows (WNCK_PAGER (pg->box), 1); //pager->rows);
663 wnck_pager_set_display_mode (WNCK_PAGER (pg->box),WNCK_PAGER_DISPLAY_CONTENT);
664 //pager->show_names ? WNCK_PAGER_DISPLAY_NAME : WNCK_PAGER_DISPLAY_CONTENT);
665 //gtk_widget_show (pg->box);
666 //gtk_container_add (GTK_CONTAINER (plugin), pg->box);
667
668 //gtk_container_set_border_width (GTK_CONTAINER (pg->box), 2);
669 gtk_widget_show(pg->box);
670
671 gtk_container_set_border_width (GTK_CONTAINER (plug->pwid), 1);
672 gtk_container_add(GTK_CONTAINER(plug->pwid), pg->box);
673 //pg->eb = pg->box;
674
675 //pg->ratio = (gfloat)gdk_screen_width() / (gfloat)gdk_screen_height();
676 //pg->scaley = (gfloat)pg->dh / (gfloat)gdk_screen_height();
677 //pg->scalex = (gfloat)pg->dw / (gfloat)gdk_screen_width();
678
679 //pager_rebuild_all(fbev, pg);
680 //do_net_current_desktop(fbev, pg);
681 //do_net_client_list_stacking(fbev, pg);
682
683 // gdk_window_add_filter(NULL, (GdkFilterFunc)pager_event_filter, pg );
684
685 // g_signal_connect (G_OBJECT (fbev), "current_desktop",
686 // G_CALLBACK (do_net_current_desktop), (gpointer) pg);
687 // g_signal_connect (G_OBJECT (fbev), "active_window",
688 // G_CALLBACK (do_net_active_window), (gpointer) pg);
689 // g_signal_connect (G_OBJECT (fbev), "number_of_desktops",
690 // G_CALLBACK (pager_rebuild_all), (gpointer) pg);
691 // g_signal_connect (G_OBJECT (fbev), "client_list_stacking",
692 // G_CALLBACK (do_net_client_list_stacking), (gpointer) pg);
693 RET(1);
694 }
695
696 static void
697 pager_destructor(Plugin *p)
698 {
699 pager *pg = (pager *)p->priv;
700
701 ENTER;
702 // g_signal_handlers_disconnect_by_func(G_OBJECT (fbev), do_net_current_desktop, pg);
703 // g_signal_handlers_disconnect_by_func(G_OBJECT (fbev), do_net_active_window, pg);
704 // g_signal_handlers_disconnect_by_func(G_OBJECT (fbev), pager_rebuild_all, pg);
705 // g_signal_handlers_disconnect_by_func(G_OBJECT (fbev), do_net_client_list_stacking, pg);
706 // gdk_window_remove_filter(NULL, (GdkFilterFunc)pager_event_filter, pg);
707 // while (--pg->desknum) {
708 // desk_free(pg, pg->desknum);
709 // }
710 //g_hash_table_foreach_remove(pg->htable, (GHRFunc) task_remove_all, (gpointer)pg);
711 //g_hash_table_destroy(pg->htable);
712 gtk_widget_destroy(p->pwid);
713 g_free(pg);
714 RET();
715 }
716
717 static void wnckpager_panel_configuration_changed(Plugin * p)
718 {
719 pager *pg = (pager *)p->priv;
720
721 wnck_pager_set_orientation (WNCK_PAGER (pg->box),pg->plugin->panel->orientation);
722 wnck_pager_set_n_rows (WNCK_PAGER (pg->box), pg->plugin->panel->height / 48 + 1);
723 }
724
725 PluginClass wnckpager_plugin_class = {
726
727 PLUGINCLASS_VERSIONING,
728
729 .type = "wnckpager",
730 .name = N_("WNCKPager"),
731 .version = "1.0",
732 .description = N_("WNCKpager plugin"),
733
734 /* FIXME: orientation should be handled!! */
735 .constructor = pager_wnck_constructor,
736 .destructor = pager_destructor,
737 .config = NULL,
738 .save = NULL,
739 .panel_configuration_changed = wnckpager_panel_configuration_changed
740 };