3
* Copyright (C) 2002 Jasper Huijsmans(huysmans@users.sourceforge.net)
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
25
#include <X11/Xatom.h>
27
#include <libxfce4util/i18n.h>
28
#include <libxfcegui4/libxfcegui4.h>
30
#include <panel/xfce.h>
31
#include <panel/popup.h>
32
#include <panel/settings.h>
33
#include <panel/plugins.h>
36
#include <panel/mcs_client.h>
39
static int screen_button_width[] = { 35, 45, 80, 80 };
44
NetkWorkspace *workspace;
67
GtkWidget *buttonboxes[2];
75
GPtrArray *screen_names;
85
/* GtkWidget *separators[2];*/
87
/* traditional switcher */
90
/* callback(s) we have to save for new buttons and for reorientation */
97
* we want to keep track of callbacks to be able to
98
* add them to new desktop buttons
101
signal_callback_new (const char *signal, GCallback callback, gpointer data)
103
SignalCallback *sc = g_new0 (SignalCallback, 1);
106
sc->callback = callback;
114
* traditional xfce desktop buttons
117
/* color names used for screen buttons
118
* may be used in gtk themes */
119
static char *screen_class[] = {
128
screen_button_update_label (ScreenButton * sb, const char *name)
132
switch (settings.size)
135
markup = g_strconcat ("<span size=\"smaller\">",
136
name, "</span>", NULL);
139
markup = g_strconcat ("<span size=\"larger\">",
140
name, "</span>", NULL);
143
markup = g_strdup (name);
146
gtk_label_set_markup (GTK_LABEL (sb->label), markup);
151
screen_button_pressed_cb (GtkButton * b, GdkEventButton * ev,
154
hide_current_popup_menu ();
158
netk_workspace_activate (sb->workspace);
162
if (ev->button == 3 && disable_user_config)
172
screen_button_update_size (ScreenButton * sb)
177
* calculation of height is very arbitrary. I just put here what looks
178
* good on my screen. Should probably be something a little more
181
/* don't let screen buttons get too large in vertical mode */
182
if (settings.orientation == VERTICAL && settings.size > SMALL)
183
w = screen_button_width[MEDIUM] * 3 / 4;
185
w = screen_button_width[settings.size];
187
switch (settings.size)
196
h = (top_height[LARGE] + icon_size[LARGE]) / 2 - 6;
199
h = (top_height[MEDIUM] + icon_size[MEDIUM]) / 2 - 5;
204
gtk_widget_set_size_request (sb->button, w, h);
206
screen_button_update_label (sb,
207
gtk_label_get_text (GTK_LABEL (sb->label)));
210
/* creation and destruction */
212
ws_name_changed (NetkWorkspace * ws, ScreenButton * sb)
214
const char *name = netk_workspace_get_name (ws);
216
gtk_label_set_text (GTK_LABEL (sb->label), name);
220
create_screen_button (int index, const char *name, NetkScreen * screen)
222
const char *realname;
223
ScreenButton *sb = g_new0 (ScreenButton, 1);
227
sb->workspace = netk_screen_get_workspace (screen, index);
228
realname = netk_workspace_get_name (sb->workspace);
230
if (!realname || !strlen (realname))
233
sb->cb_id = g_signal_connect (sb->workspace, "name-changed",
234
G_CALLBACK (ws_name_changed), sb);
236
sb->frame = gtk_alignment_new (0, 0, 1, 1); /* gtk_frame_new(NULL); */
237
gtk_widget_show (sb->frame);
239
sb->button = gtk_toggle_button_new ();
240
gtk_button_set_relief (GTK_BUTTON (sb->button), GTK_RELIEF_HALF);
241
gtk_widget_set_name (sb->button, screen_class[sb->index % 4]);
242
gtk_widget_show (sb->button);
243
gtk_container_add (GTK_CONTAINER (sb->frame), sb->button);
245
sb->label = gtk_label_new (realname);
246
/* gtk_misc_set_alignment(GTK_MISC(sb->label), 0.1, 0.5);*/
247
gtk_widget_show (sb->label);
248
gtk_container_add (GTK_CONTAINER (sb->button), sb->label);
250
screen_button_update_size (sb);
251
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sb->button),
254
g_signal_connect (sb->button, "button-press-event",
255
G_CALLBACK (screen_button_pressed_cb), sb);
261
screen_button_pack (ScreenButton * sb, GtkBox * box)
263
gtk_box_pack_start (box, sb->frame, TRUE, TRUE, 0);
267
screen_button_free (ScreenButton * sb)
269
g_signal_handler_disconnect (sb->workspace, sb->cb_id);
275
* it's not completely stand-alone now, but perhaps we should make it a
276
* separate widget (?)
279
cde_pager_update_size (CdePager * pager)
283
for (li = pager->buttons; li; li = li->next)
285
ScreenButton *sb = li->data;
287
screen_button_update_size (sb);
290
/* check if we can rearrange the buttons (== horizontal mode) */
291
if (!pager->buttonboxes[1])
294
if (settings.size > SMALL)
295
gtk_widget_show (pager->buttonboxes[1]);
297
gtk_widget_hide (pager->buttonboxes[1]);
299
/* remove the buttons ... */
300
for (li = pager->buttons; li; li = li->next)
302
ScreenButton *sb = li->data;
304
g_object_ref (sb->frame);
305
gtk_container_remove (GTK_CONTAINER (sb->frame->parent), sb->frame);
308
/* ... and put them back again */
309
for (li = pager->buttons; li; li = li->next)
311
ScreenButton *sb = li->data;
313
if (settings.size <= SMALL || sb->index % 2 == 0)
315
gtk_box_pack_start (GTK_BOX (pager->buttonboxes[0]), sb->frame,
320
gtk_box_pack_start (GTK_BOX (pager->buttonboxes[1]), sb->frame,
324
g_object_unref (sb->frame);
329
cde_pager_attach_callback (CdePager * pager, SignalCallback * sc)
333
for (li = pager->buttons; li; li = li->next)
335
ScreenButton *sb = li->data;
337
g_signal_connect (sb->button, sc->signal, sc->callback, sc->data);
342
cde_pager_add_button (CdePager * pager, GList * callbacks, GPtrArray * names)
345
int i, index, active;
349
index = g_list_length (pager->buttons);
351
netk_workspace_get_number (netk_screen_get_active_workspace
354
for (i = names->len; i < index + 1; i++)
358
sprintf (tmp, "%d", i + 1);
360
g_ptr_array_add (names, g_strdup (tmp));
363
name = g_ptr_array_index (names, index);
364
sb = create_screen_button (index, name, pager->screen);
366
pager->buttons = g_list_append (pager->buttons, sb);
368
if (settings.orientation == VERTICAL || settings.size <= SMALL ||
371
screen_button_pack (sb, GTK_BOX (pager->buttonboxes[0]));
375
screen_button_pack (sb, GTK_BOX (pager->buttonboxes[1]));
378
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sb->button),
381
for (li = callbacks; li; li = li->next)
383
SignalCallback *sc = li->data;
385
g_signal_connect (sb->button, sc->signal, sc->callback, sc->data);
390
cde_pager_remove_button (CdePager * pager)
395
li = g_list_last (pager->buttons);
398
pager->buttons = g_list_delete_link (pager->buttons, li);
400
gtk_widget_destroy (sb->frame);
402
screen_button_free (sb);
406
cde_pager_set_active (CdePager * pager, NetkWorkspace * ws)
410
for (li = pager->buttons; li; li = li->next)
412
ScreenButton *sb = li->data;
414
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sb->button),
415
sb->workspace == ws);
420
create_cde_pager (NetkScreen * screen, GPtrArray * names)
424
CdePager *pager = g_new0 (CdePager, 1);
426
pager->screen = screen;
428
n = netk_screen_get_workspace_count (screen);
430
if (settings.orientation == HORIZONTAL)
434
pager->box = gtk_vbox_new (FALSE, 0);
435
gtk_widget_show (pager->box);
437
spacer = gtk_alignment_new (0, 0, 0, 0);
438
gtk_widget_show (spacer);
439
gtk_box_pack_start (GTK_BOX (pager->box), spacer, TRUE, TRUE, 0);
441
pager->buttonboxes[0] = gtk_hbox_new (TRUE, 2);
442
gtk_widget_show (pager->buttonboxes[0]);
443
gtk_box_pack_start (GTK_BOX (pager->box), pager->buttonboxes[0],
446
pager->buttonboxes[1] = gtk_hbox_new (TRUE, 2);
447
gtk_widget_show (pager->buttonboxes[1]);
448
gtk_box_pack_start (GTK_BOX (pager->box), pager->buttonboxes[1],
451
spacer = gtk_alignment_new (0, 0, 0, 0);
452
gtk_widget_show (spacer);
453
gtk_box_pack_start (GTK_BOX (pager->box), spacer, TRUE, TRUE, 0);
457
pager->box = pager->buttonboxes[0] = gtk_vbox_new (TRUE, 2);
458
gtk_widget_show (pager->box);
461
for (i = 0; i < n; i++)
463
/* no callbacks yet */
464
cde_pager_add_button (pager, NULL, names);
471
cde_pager_free (CdePager * pager)
475
for (li = pager->buttons; li; li = li->next)
477
ScreenButton *sb = li->data;
479
screen_button_free (sb);
482
g_list_free (pager->buttons);
490
/* static prototypes */
491
static void arrange_switcher (t_switcher * sw);
495
switcher_set_size (Control * control, int size)
499
gtk_widget_set_size_request (control->base, -1, -1);
503
cde_pager_update_size (sw->cde_pager);
507
switcher_set_orientation (Control * control, int orientation)
513
arrange_switcher (sw);
514
switcher_set_size (control, settings.size);
517
/* creation, destruction and configuration
518
* ---------------------------------------
521
switcher_attach_callback (Control * control, const char *signal,
522
GCallback callback, gpointer data)
529
sc = signal_callback_new (signal, callback, data);
530
sw->callbacks = g_list_append (sw->callbacks, sc);
532
cde_pager_attach_callback (sw->cde_pager, sc);
536
arrange_switcher (t_switcher * sw)
539
gboolean vertical = settings.orientation == VERTICAL;
541
/* destroy existing widgets */
544
cde_pager_free (sw->cde_pager);
546
gtk_widget_destroy (sw->box);
549
/* then create new ones */
552
sw->box = gtk_vbox_new (FALSE, 1);
553
/* sw->separators[0] = gtk_hseparator_new ();
554
sw->separators[1] = gtk_hseparator_new ();*/
558
sw->box = gtk_hbox_new (FALSE, 0);
559
/* sw->separators[0] = gtk_vseparator_new ();
560
sw->separators[1] = gtk_vseparator_new ();*/
563
sw->cde_pager = create_cde_pager (sw->screen, sw->screen_names);
565
/* show the widgets */
566
gtk_widget_show (sw->box);
568
/* gtk_widget_show (sw->separators[0]);
569
gtk_widget_show (sw->separators[1]);
571
/* packing the widgets */
572
gtk_container_add (GTK_CONTAINER (sw->frame), sw->box);
574
/* gtk_box_pack_start (GTK_BOX (sw->box), sw->separators[0], TRUE, TRUE, 2);
576
gtk_box_pack_start (GTK_BOX (sw->box), sw->cde_pager->box, TRUE, TRUE, 2);
578
/* gtk_box_pack_start (GTK_BOX (sw->box), sw->separators[1], TRUE, TRUE, 2);
580
/* attach callbacks */
581
for (li = sw->callbacks; li; li = li->next)
583
SignalCallback *cb = li->data;
585
cde_pager_attach_callback (sw->cde_pager, cb);
591
switcher_set_current_screen (NetkScreen * screen, t_switcher * sw)
595
ws = netk_screen_get_active_workspace (sw->screen);
597
cde_pager_set_active (sw->cde_pager, ws);
601
switcher_screen_created (NetkScreen * screen, NetkWorkspace * ws,
604
cde_pager_add_button (sw->cde_pager, sw->callbacks, sw->screen_names);
608
switcher_screen_destroyed (NetkScreen * screen, NetkWorkspace * ws,
611
cde_pager_remove_button (sw->cde_pager);
615
switcher_new (NetkScreen * screen)
617
t_switcher *sw = g_new0 (t_switcher, 1);
622
g_ptr_array_sized_new (netk_screen_get_workspace_count (screen));
624
sw->frame = gtk_alignment_new (0.5, 0.5, 0.8, 0.8);
625
gtk_widget_show (sw->frame);
627
/* this creates all widgets */
628
arrange_switcher (sw);
631
g_signal_connect (sw->screen, "active-workspace-changed",
632
G_CALLBACK (switcher_set_current_screen), sw);
635
g_signal_connect (sw->screen, "workspace-created",
636
G_CALLBACK (switcher_screen_created), sw);
638
sw->ws_destroyed_id =
639
g_signal_connect (sw->screen, "workspace-destroyed",
640
G_CALLBACK (switcher_screen_destroyed), sw);
646
switcher_free (Control * control)
653
g_signal_handler_disconnect (sw->screen, sw->ws_changed_id);
654
g_signal_handler_disconnect (sw->screen, sw->ws_created_id);
655
g_signal_handler_disconnect (sw->screen, sw->ws_destroyed_id);
657
cde_pager_free (sw->cde_pager);
659
for (li = sw->callbacks; li; li = li->next)
662
g_list_free (sw->callbacks);
667
/* Switcher panel control
668
* ----------------------
671
create_switcher_control (Control * control)
676
screen = netk_screen_get_default ();
678
netk_screen_force_update (screen);
679
sw = switcher_new (screen);
680
netk_screen_force_update (screen);
682
gtk_container_add (GTK_CONTAINER (control->base), sw->frame);
685
control->with_popup = FALSE;
687
switcher_set_size (control, settings.size);
693
xfce_control_class_init (ControlClass * cc)
695
cc->name = "switcher";
696
cc->caption = _("Desktop switcher");
698
cc->create_control = (CreateControlFunc) create_switcher_control;
700
cc->free = switcher_free;
701
cc->attach_callback = switcher_attach_callback;
703
cc->set_orientation = switcher_set_orientation;
704
cc->set_size = switcher_set_size;
708
XFCE_PLUGIN_CHECK_INIT