Browse Source

Add gtk2 based panel

(Old svn revision: 3243)
upstream/xfce4-panel-4.10.1
Jasper Huijsmans 20 years ago
parent
commit
d7074befad
  1. 33
      Makefile
  2. 68
      README
  3. 128
      README.xml
  4. 435
      builtins.c
  5. 14
      builtins.h
  6. 534
      callbacks.c
  7. 63
      callbacks.h
  8. 485
      central.c
  9. 52
      central.h
  10. 786
      dialogs.c
  11. 12
      dialogs.h
  12. 199
      icons.c
  13. 73
      icons.h
  14. 23
      icons/addicon.xpm
  15. 10
      icons/close.xpm
  16. 62
      icons/diag_icon.xpm
  17. 13
      icons/down.xpm
  18. 60
      icons/edit.xpm
  19. 64
      icons/file1.xpm
  20. 62
      icons/file2.xpm
  21. 58
      icons/games.xpm
  22. 30
      icons/handle.xpm
  23. 10
      icons/iconify.xpm
  24. 62
      icons/mail.xpm
  25. 59
      icons/man.xpm
  26. 60
      icons/menu_icon.xpm
  27. 27
      icons/miniinfo.xpm
  28. 29
      icons/minilock.xpm
  29. 31
      icons/minipalet.xpm
  30. 27
      icons/minipower.xpm
  31. 60
      icons/multimedia.xpm
  32. 61
      icons/network.xpm
  33. 59
      icons/nomail.xpm
  34. 65
      icons/oldmail.xpm
  35. 64
      icons/paint.xpm
  36. 61
      icons/print.xpm
  37. 60
      icons/schedule.xpm
  38. 62
      icons/sound.xpm
  39. 64
      icons/terminal.xpm
  40. 67
      icons/trash_empty.xpm
  41. 70
      icons/trash_full.xpm
  42. 69
      icons/unknown.xpm
  43. 12
      icons/up.xpm
  44. 66
      icons/xfce_icon.xpm
  45. 226
      item.c
  46. 36
      item.h
  47. 189
      module.c
  48. 57
      module.h
  49. 228
      move.c
  50. 36
      move.h
  51. 21
      plugins/Makefile
  52. 301
      plugins/mailcheck.c
  53. 180
      popup.c
  54. 55
      popup.h
  55. 616
      settings.c
  56. 15
      settings.h
  57. 346
      side.c
  58. 73
      side.h
  59. 178
      wmhints.c
  60. 18
      wmhints.h
  61. 357
      xfce.c
  62. 140
      xfce.h

33
Makefile

@ -0,0 +1,33 @@
OBJS = xfce.o central.o side.o \
popup.o item.o module.o settings.o icons.o wmhints.o \
builtins.o move.o dialogs.o callbacks.o
PROG = xfce2
CFLAGS = -Wall -DGTK_DISABLE_DEPRECATED -g
GTK_CFLAGS = `pkg-config --cflags gtk+-2.0 gmodule-2.0 libxml-2.0`
GTK_LIBS = `pkg-config --libs gtk+-2.0 gmodule-2.0 libxml-2.0`
COMPILE = $(CC) $(CFLAGS) $(GTK_CFLAGS) -c
subdirs = plugins
all: $(PROG) sub
$(PROG): $(OBJS)
$(CC) $(GTK_LIBS) -o $(PROG) $(OBJS)
mailcheck.o:
$(CC) -fPIC $(GTK_CFLAGS) -c mailcheck.c -o mailcheck.o
sub:
(cd plugins; make)
%.o: %.c %.h xfce.h
$(COMPILE) -o $@ $<
clean:
-rm $(OBJS) $(PROG)
(cd plugins; make clean)

68
README

@ -0,0 +1,68 @@
README for xfce version 4.x
---------------------------
WHAT IS IT ?
------------
'xfce' is the panel of the XFce Desktop Environment. It is modeled after the CDE
panel and, of course, previous versions of xfce.
This version is based on GTK2 and should have all the advantages that come with
this new and improved toolkit (see http://www.gtk.org).
WHAT'S NEW ?
------------
Apart from the toolkit changes the underlying framework of the panel has also
changed completely. All interactions with the window manager take place through
the new window manager hints as defined on http://www.freedesktop.org. This
means that you will need a compliant window manager for xfce to function
properly (preferably xfwm4 ;-).
INFO FOR DEVELOPERS
-------------------
This section gives an overview of the internal design of the panel to assist
anyone who wants to read the code.
Several structures are defined to describe the different parts of the panel.
The panel consists of three subpanels: two side panels (left and right) and a
central panel. The central panel contains the desktop switcher and four small
butons. The side panels consist of several panel groups.
A panel group in turn consists of a top and a bottom widget. The top widget is
usually a popup button, except for the outer groups on both panels where it is a
move handle. The bottom widget is either a normal panel item (icon button with
run action) or a module.
A module can be a builtin module or an external plugin. It usually is an
indicator of some sort, e.g. a clock, a trashcan and a mail checker. For
demonstration purposes xfce comes with a builtin clock and trashcan and a sample
plugin mailchecker. plugins are loaded throught the gmodule interface.
The panel defines a sort of API where commands are passed on through the
hierarchy of structures.
*** UNFINISHED PART ***
Popup menus are not yet implemented.
Currently there is no configuration framework yet. There are functions to change
the size of the panel (small, medium or large) and the style (new or old). The
number of desktops can be set in settings.c for now.
The panel can switch desktops and, even nicer, reacts to changes made by other
programs, both for the current desktop and the number of desktops.
C STRUCTURE HIERARCHY
---------------------
This only defines the relation between structures. Their members are omitted.
You can find them in their corresponding header files.
XfcePanel panel
SidePanel *left_panel
PanelGroup *groups [NBGROUPS]
MoveHandle handle / PanelPopup popup
PanelItem item / PanelModule module
CentralPanel central_panel
ScreenButton *screen_buttons [NBSCREENS]
SidePanel right_panel
PanelGroup *groups [NBGROUPS]
MoveHandle handle / PanelPopup popup
PanelItem item / PanelModule module

128
README.xml

@ -0,0 +1,128 @@
Proposal for xml config file for xfce
-------------------------------------
namespace: xfce:"http://www.xfce.org/xfce"
root: Panel
name: Panel
parent: none
properties: size (int), popupsize (int), style (int), icontheme (string)
children:
Position
Central
Left
Right
name: Position
parent: Panel
properties: x (int), y (int)
content: none
children: none
name: Central
parent: Panel
properties: none
content: none
children:
Screens
Lock
Power
name: Left
parent: Panel
properties: visible
content: none
children:
Group
name Right
parent: Panel
properties: visible
content: none
children:
Group
name: Screens
parent: Central
properties: visible (int)
content: none
children:
Screen
name: Screen
parent: Screens
properties: none
content: screen name
children: none
name: Lock
parent: Central
properties: none
content: lock command
children: none
name: Power
parent: Central
properties: ?
content: ? something to quit the session
children: none
name: Group
parent: Left, Right
properties: none
content: none
children:
Popup
Item
Module
name: Popup
parent: Group
properties: none
content: none
children:
Item
name: Item
parent: Group, Popup
properties: none
content: none
children:
Caption
Command
Tooltip
Icon
:close
name: Module
parent: Group
properties: id (int)
content: module name
children: none
name: Caption
parent: Item
properties: none
content: label for item
children: none
name: Command
parent: Item
properties: none
content: command to execute
children: none
name: Tooltip
parent: Item
properties: none
content: tooltip for item
children: none
name: Icon
parent: Item
properties: id (int)
content: path to icon
children: none
Example
-------

435
builtins.c

@ -0,0 +1,435 @@
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <gtk/gtk.h>
#include "xfce.h"
#include "builtins.h"
#include "callbacks.h"
#include "icons.h"
extern GtkTooltips *tooltips;
/*****************************************************************************/
enum
{
TARGET_STRING,
TARGET_ROOTWIN,
TARGET_URL
};
static GtkTargetEntry target_table[] = {
{"text/uri-list", 0, TARGET_URL},
{"STRING", 0, TARGET_STRING}
};
static guint n_targets = sizeof (target_table) / sizeof (target_table[0]);
/*****************************************************************************/
/* clock module */
typedef struct
{
GtkWidget *eventbox;
int size;
gboolean show_colon;
int interval;
int timeout;
GtkWidget *frame;
GtkWidget *label;
}
t_clock;
/* "There can be only one" */
gboolean panel_has_clock = FALSE;
int secs_in_day = 24 * 60 * 60;
static gboolean
adjust_time (t_clock *clock)
{
GTimeVal tv;
int today;
int hrs, mins;
char *text, *markup;
g_get_current_time (&tv);
today = tv.tv_sec % secs_in_day;
hrs = today / 3600;
mins = (today % 3600) / 60;
text = g_strdup_printf ("%.2d%c%.2d",
hrs + 2, clock->show_colon ? ':' : ' ', mins);
switch (clock->size)
{
case SMALL:
markup = g_strconcat ("<tt><span size=\"smaller\">",
text, "</span></tt>", NULL);
break;
case LARGE:
markup = g_strconcat ("<tt><span size=\"larger\">",
text, "</span></tt>", NULL);
break;
default:
markup = g_strconcat ("<tt>", text, "</tt>", NULL);
break;
}
clock->show_colon = !clock->show_colon;
gtk_label_set_markup (GTK_LABEL (clock->label), markup);
g_free (text);
g_free (markup);
return TRUE;
}
t_clock *
clock_init (GtkWidget *eventbox)
{
t_clock *clock = g_new (t_clock, 1);
panel_has_clock = TRUE;
clock->size = MEDIUM;
clock->interval = 1000; /* 1 sec */
clock->timeout = 0;
clock->frame = gtk_frame_new (NULL);
gtk_container_set_border_width (GTK_CONTAINER (clock->frame), 4);
gtk_frame_set_shadow_type (GTK_FRAME (clock->frame), GTK_SHADOW_IN);
gtk_container_add (GTK_CONTAINER (eventbox), clock->frame);
clock->eventbox = gtk_event_box_new ();
gtk_container_add (GTK_CONTAINER (clock->frame), clock->eventbox);
clock->label = gtk_label_new (NULL);
gtk_container_add (GTK_CONTAINER (clock->eventbox), clock->label);
gtk_widget_show_all (clock->frame);
adjust_time (clock);
return clock;
}
void
clock_run (t_clock *clock)
{
clock->timeout = g_timeout_add (clock->interval,
(GSourceFunc) adjust_time, clock);
}
void
clock_stop (t_clock *clock)
{
panel_has_clock = FALSE;
g_source_remove (clock->timeout);
gtk_widget_destroy (clock->frame);
g_free (clock);
}
void
clock_set_size (t_clock *clock, int size)
{
int s = icon_size (size);
clock->size = size;
gtk_widget_set_size_request (clock->frame, s, s);
}
void
clock_set_style (t_clock *clock, int style)
{
if (style == OLD_STYLE)
{
gtk_widget_set_name (clock->frame, "gxfce_color2");
gtk_widget_set_name (clock->label, "gxfce_color2");
gtk_widget_set_name (clock->eventbox, "gxfce_color2");
}
else
{
gtk_widget_set_name (clock->frame, "gxfce_color4");
gtk_widget_set_name (clock->label, "gxfce_color4");
gtk_widget_set_name (clock->eventbox, "gxfce_color4");
}
}
void
clock_configure (void)
{
}
gboolean
create_clock_module (PanelModule *pm)
{
if (panel_has_clock)
return FALSE;
pm->init = (gpointer) clock_init;
pm->run = (gpointer) clock_run;
pm->stop = (gpointer) clock_stop;
pm->set_size = (gpointer) clock_set_size;
pm->set_style = (gpointer) clock_set_style;
pm->configure = (gpointer) clock_configure;
pm->data = (gpointer) clock_init (pm->eventbox);
return TRUE;
}
/*****************************************************************************/
/* trashcan module */
typedef struct
{
char *dirname;
char *command;
int interval;
gboolean stop;
int size;
gboolean empty;
int changed;
GdkPixbuf *current_pb;
GdkPixbuf *empty_pb;
GdkPixbuf *full_pb;
GtkWidget *button;
GtkWidget *image;
}
t_trash;
static void
free_trash (t_trash *trash)
{
g_free (trash->dirname);
g_free (trash->command);
g_object_unref (trash->empty_pb);
g_object_unref (trash->full_pb);
}
static void
trash_set_scaled_image (t_trash *trash)
{
GdkPixbuf *pb;
int width, height, bw;
bw = trash->size == SMALL ? 0 : 2;
width = height = icon_size (trash->size);
gtk_container_set_border_width (GTK_CONTAINER (trash->button), bw);
gtk_widget_set_size_request (trash->button, width + 4, height + 4);
pb = gdk_pixbuf_scale_simple (trash->current_pb,
width - 2 * bw,
height - 2 * bw,
GDK_INTERP_BILINEAR);
gtk_image_set_from_pixbuf (GTK_IMAGE (trash->image), pb);
g_object_unref (pb);
}
static gboolean
check_trash (t_trash *trash)
{
GDir *dir = g_dir_open (trash->dirname, 0, NULL);
const char *file;
char text[MAXSTRLEN];
if (dir)
file = g_dir_read_name (dir);
if (!dir || !file)
{
if (dir)
g_dir_close (dir);
if (!trash->empty)
{
trash->current_pb = trash->empty_pb;
trash->empty = TRUE;
trash->changed = TRUE;
gtk_tooltips_set_tip (tooltips, trash->button,
_("Trashcan: 0 files"), NULL);
}
}
else
{
struct stat s;
int number = 0;
int size = 0;
char *cwd = g_get_current_dir ();
chdir (trash->dirname);
if (trash->empty)
{
trash->current_pb = trash->full_pb;
trash->empty = FALSE;
trash->changed = TRUE;
}
while (file)
{
number++;
stat (file, &s);
size += s.st_size;
file = g_dir_read_name (dir);
}
chdir (cwd);
g_free (cwd);
g_dir_close (dir);
sprintf (text, _("Trashcan: %d files / %d kb"), number, size / 1024);
gtk_tooltips_set_tip (tooltips, trash->button,
text, NULL);
}
if (trash->changed)
{
trash_set_scaled_image (trash);
trash->changed = FALSE;
}
if (trash->stop)
{
free_trash (trash);
return FALSE;
}
else
return TRUE;
}
void
trash_drop_cb (GtkWidget * widget, GdkDragContext * context,
gint x, gint y, GtkSelectionData * data,
guint info, guint time, gpointer cbdata)
{
GList *fnames, *fnp;
guint count;
char *execute, *cmd;
fnames = gnome_uri_list_extract_filenames ((char *) data->data);
count = g_list_length (fnames);
if (count > 0)
{
execute = (char *) g_malloc (MAXSTRLEN);
cmd = (char *) cbdata;
strcpy (execute, cmd);
for (fnp = fnames; fnp; fnp = fnp->next, count--)
{
strcat (execute, " ");
strncat (execute, (char *) (fnp->data), MAXSTRLEN - 1);
}
exec_cmd (execute);
g_free (execute);
}
gnome_uri_list_free_strings (fnames);
gtk_drag_finish (context, (count > 0), (context->action == GDK_ACTION_MOVE), time);
}
t_trash *
trash_init (GtkWidget *eventbox)
{
const char *home = g_getenv ("HOME");
t_trash *trash = g_new (t_trash, 1);
trash->dirname = g_strconcat (home, "/.xfce/trash", NULL);
trash->command = g_strdup ("xftrash");
trash->interval = 2000; /* 2 sec */
trash->stop = FALSE;
trash->size = MEDIUM;
trash->empty = TRUE;
trash->changed = FALSE;
trash->empty_pb = get_trashcan_pixbuf (TRASH_EMPTY_ICON);
trash->full_pb = get_trashcan_pixbuf (TRASH_FULL_ICON);
trash->button = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (trash->button), GTK_RELIEF_NONE);
trash->image = gtk_image_new ();
trash->current_pb = trash->empty_pb;
trash_set_scaled_image (trash);
gtk_container_add (GTK_CONTAINER (trash->button), trash->image);
gtk_container_add (GTK_CONTAINER (eventbox), trash->button);
gtk_widget_show_all (trash->button);
gtk_tooltips_set_tip (tooltips, trash->button,
_("Trashcan: 0 files"), NULL);
check_trash (trash);
/* signals */
if (trash->command)
{
g_signal_connect_swapped (trash->button, "clicked",
G_CALLBACK (exec_cmd), trash->command);
gtk_drag_dest_set (trash->button, GTK_DEST_DEFAULT_ALL,
target_table, n_targets, GDK_ACTION_COPY);
g_signal_connect (trash->button, "drag_data_received",
G_CALLBACK (trash_drop_cb), trash->command);
}
return trash;
}
void
trash_run (t_trash *trash)
{
g_timeout_add (trash->interval, (GSourceFunc) check_trash, trash);
}
void
trash_stop (t_trash *trash)
{
trash->stop = TRUE;
}
void trash_set_size (t_trash *trash, int size)
{
trash->size = size;
trash_set_scaled_image (trash);
}
gboolean
create_trash_module (PanelModule *pm)
{
pm->init = (gpointer) trash_init;
pm->run = (gpointer) trash_run;
pm->stop = (gpointer) trash_stop;
pm->set_size = (gpointer) trash_set_size;
pm->data = (gpointer) trash_init (pm->eventbox);
return TRUE;
}

14
builtins.h

@ -0,0 +1,14 @@
#ifndef __XFCE_BUILTINS_H__
#define __XFCE_BUILTINS_H__
#include "xfce.h"
#include "module.h"
/* builtin modules */
gboolean create_clock_module (PanelModule *pm);
gboolean create_trash_module (PanelModule *pm);
gboolean create_mailcheck_module (PanelModule *pm);
#endif /* __XFCE_BUILTINS_H__ */

534
callbacks.c

@ -0,0 +1,534 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <gtk/gtk.h>
#include "xfce.h"
#include "callbacks.h"
#include "dialogs.h"
#include "central.h"
#include "side.h"
#include "item.h"
#include "popup.h"
#include "icons.h"
static PanelPopup *open_popup = NULL;
void hide_current_popup_menu (void);
/*****************************************************************************/
/* useful utility functions */
void
exec_cmd (const char *cmd)
{
GError *error = NULL; /* this must be NULL to prevent crash :( */
if (!g_spawn_command_line_async (cmd, &error))
{
GtkWidget *dialog;
char *msg;
msg = g_strcompress (error->message);
dialog = gtk_message_dialog_new (NULL,
GTK_DIALOG_MODAL,
GTK_MESSAGE_WARNING,
GTK_BUTTONS_OK, msg);
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
g_free (msg);
}
}
/*** the next three routines are taken straight from gnome-libs so that the
gtk-only version can receive drag and drops as well ***/
/**
* gnome_uri_list_free_strings:
* @list: A GList returned by gnome_uri_list_extract_uris() or gnome_uri_list_extract_filenames()
*
* Releases all of the resources allocated by @list.
*/
void
gnome_uri_list_free_strings (GList * list)
{
g_list_foreach (list, (GFunc) g_free, NULL);
g_list_free (list);
}
/**
* gnome_uri_list_extract_uris:
* @uri_list: an uri-list in the standard format.
*
* Returns a GList containing strings allocated with g_malloc
* that have been splitted from @uri-list.
*/
GList *
gnome_uri_list_extract_uris (const gchar * uri_list)
{
const gchar *p, *q;
gchar *retval;
GList *result = NULL;
g_return_val_if_fail (uri_list != NULL, NULL);
p = uri_list;
/* We don't actually try to validate the URI according to RFC
* 2396, or even check for allowed characters - we just ignore
* comments and trim whitespace off the ends. We also
* allow LF delimination as well as the specified CRLF.
*/
while (p)
{
if (*p != '#')
{
while (isspace ((int) (*p)))
p++;
q = p;
while (*q && (*q != '\n') && (*q != '\r'))
q++;
if (q > p)
{
q--;
while (q > p && isspace ((int) (*q)))
q--;
retval = (char *) g_malloc (q - p + 2);
strncpy (retval, p, q - p + 1);
retval[q - p + 1] = '\0';
result = g_list_prepend (result, retval);
}
}
p = strchr (p, '\n');
if (p)
p++;
}
return g_list_reverse (result);
}
/**
* gnome_uri_list_extract_filenames:
* @uri_list: an uri-list in the standard format
*
* Returns a GList containing strings allocated with g_malloc
* that contain the filenames in the uri-list.
*
* Note that unlike gnome_uri_list_extract_uris() function, this
* will discard any non-file uri from the result value.
*/
GList *
gnome_uri_list_extract_filenames (const gchar * uri_list)
{
GList *tmp_list, *node, *result;
g_return_val_if_fail (uri_list != NULL, NULL);
result = gnome_uri_list_extract_uris (uri_list);
tmp_list = result;
while (tmp_list)
{
gchar *s = (char *) tmp_list->data;
node = tmp_list;
tmp_list = tmp_list->next;
if (!strncmp (s, "file:", 5))
{
/* added by Jasper Huijsmans
remove leading multiple slashes */
if (!strncmp (s + 5, "///", 3))
node->data = g_strdup (s + 7);
else
node->data = g_strdup (s + 5);
}
else
{
node->data = g_strdup (s);
}
g_free (s);
}
return result;
}
/*****************************************************************************/
/* panel */
gboolean
panel_delete_cb (GtkWidget * window, GdkEvent * ev, gpointer data)
{
GtkWidget *dialog;
int response;
hide_current_popup_menu ();
dialog = gtk_message_dialog_new (GTK_WINDOW (window),
GTK_DIALOG_MODAL |
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_QUESTION, GTK_BUTTONS_YES_NO,
_
("The panel recieved a request from the window manager\n"
"to quit. Usually this is by accident. If you want to\n"
"continue using the panel choose \'No\'\n\n"
"Do you want to quit the panel?"));
gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
response = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_destroy (dialog);
if (response == GTK_RESPONSE_YES)
quit ();
return TRUE;
}
/*****************************************************************************/
/* central panel */
gboolean
screen_button_pressed_cb (GtkButton * b, GdkEventButton * ev,
ScreenButton * sb)
{
hide_current_popup_menu ();
if (ev->button != 3)
return FALSE;
return TRUE;
}
/* temporary functions for testing purposes */
void
switch_size_cb (void)
{
static int size = MEDIUM;
size = size == MEDIUM ? SMALL : size == SMALL ? LARGE : MEDIUM;
panel_set_size (size);
panel_set_popup_size (size);
}
void
switch_style_cb (void)
{
static int style = NEW_STYLE;
style = style == NEW_STYLE ? OLD_STYLE : NEW_STYLE;
panel_set_style (style);
}
/**/ void
mini_lock_cb (char *cmd)
{
hide_current_popup_menu ();
exec_cmd (cmd);
}
void
mini_info_cb (void)
{
hide_current_popup_menu ();
switch_size_cb ();
}
void
mini_palet_cb (void)
{
hide_current_popup_menu ();
switch_style_cb ();
}
void
mini_power_cb (GtkButton * b, GdkEventButton * ev, gpointer data)
{
int w, h;
hide_current_popup_menu ();
gdk_window_get_size (ev->window, &w, &h);
/* we have to check if the pointer is still inside the button */
if (ev->x < 0 || ev->x > w || ev->y < 0 || ev->y > h)
{
gtk_button_released (b);
return;
}
if (ev->button == 1)
quit ();
else
restart ();
}
/*****************************************************************************/
/* side panel */
void
iconify_cb (void)
{
hide_current_popup_menu ();
iconify_panel ();
}
gboolean
group_button_press_cb (GtkButton * b, GdkEventButton * ev, PanelGroup * pg)
{
hide_current_popup_menu ();
if (ev->button != 3)
return FALSE;
return TRUE;
}
/*****************************************************************************/
/* popup */
static void
hide_popup (PanelPopup * pp)
{
if (open_popup == pp)
open_popup = NULL;
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pp->button), FALSE);
gtk_image_set_from_pixbuf (GTK_IMAGE (pp->arrow_image), pp->up);
gtk_widget_hide (pp->window);
if (pp->detached)
{
pp->detached = FALSE;
gtk_widget_show (pp->tearoff_button);
gtk_window_set_decorated (GTK_WINDOW (pp->window), FALSE);
}
}
static void
show_popup (PanelPopup * pp)
{
GtkRequisition req1, req2;
GdkWindow *p;
int xb, yb, xp, yp, x, y;
if (open_popup)
hide_popup (open_popup);
if (!pp->detached)
open_popup = pp;
gtk_image_set_from_pixbuf (GTK_IMAGE (pp->arrow_image), pp->down);
if (!GTK_WIDGET_REALIZED (pp->button))
gtk_widget_realize (pp->button);
gtk_widget_size_request (pp->button, &req1);
xb = pp->button->allocation.x;
yb = pp->button->allocation.y;
p = gtk_widget_get_parent_window (pp->button);
gdk_window_get_root_origin (p, &xp, &yp);
x = xb + xp + req1.width / 2;
y = yb + yp;
if (!GTK_WIDGET_REALIZED (pp->window))
gtk_widget_realize (pp->window);
gtk_widget_size_request (pp->window, &req2);
/* show upwards or downwards ?
* and make detached menu appear loose from the button */
if (y < req2.height && gdk_screen_height () - y > req2.height)
{
y = y + req1.height;
if (pp->detached)
y = y + 30;
}
else
{
y = y - req2.height;
if (pp->detached)
y = y - 15;
}
x = x - req2.width / 2;
if (x < 0)
x = 0;
if (x + req2.width > gdk_screen_width ())
x = gdk_screen_width () - req2.width;
gtk_window_move (GTK_WINDOW (pp->window), x, y);
gtk_widget_show (pp->window);
}
void
hide_current_popup_menu (void)
{
if (open_popup)
hide_popup (open_popup);
}
void
toggle_popup (GtkWidget * button, PanelPopup * pp)
{
hide_current_popup_menu ();
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
show_popup (pp);
else
hide_popup (pp);
}
void
tearoff_popup (GtkWidget * button, PanelPopup * pp)
{
open_popup = NULL;
pp->detached = TRUE;
gtk_widget_hide (pp->window);
gtk_widget_hide (pp->tearoff_button);
gtk_window_set_decorated (GTK_WINDOW (pp->window), TRUE);
show_popup (pp);
}
gboolean
delete_popup (GtkWidget * window, GdkEvent * ev, PanelPopup * pp)
{
hide_popup (pp);
return TRUE;
}
/*****************************************************************************/
/* item */
void
addtomenu_item_drop_cb (GtkWidget * widget, GdkDragContext * context,
gint x, gint y, GtkSelectionData * data,
guint info, guint time, PanelPopup * pp)
{
GList *fnames, *fnp;
guint count;
fnames = gnome_uri_list_extract_filenames ((char *) data->data);
count = g_list_length (fnames);
if (count > 0)
{
for (fnp = fnames; fnp; fnp = fnp->next, count--)
{
char *cmd;
PanelItem *pi = panel_item_new (pp);
if (!(cmd = g_find_program_in_path ((char *) fnp->data)))
continue;
pi->in_menu = TRUE;
pi->command = cmd;
pi->caption = g_path_get_basename (cmd);
pi->caption[0] = g_ascii_toupper (pi->caption[0]);
create_panel_item (pi);
pp->items = g_list_prepend (pp->items, pi);
gtk_size_group_add_widget (pp->hgroup, pi->image);
gtk_box_pack_start (GTK_BOX (pp->vbox), pi->button, TRUE, TRUE, 0);
gtk_box_reorder_child (GTK_BOX (pp->vbox), pi->button, 2);
gtk_button_clicked (GTK_BUTTON (pp->button));
gtk_button_clicked (GTK_BUTTON (pp->button));
}
}
gnome_uri_list_free_strings (fnames);
gtk_drag_finish (context, (count > 0), (context->action == GDK_ACTION_MOVE),
time);
}
void addtomenu_item_click_cb (GtkButton * b, PanelPopup * pp)
{
add_item_dialog (pp);
}
void
item_drop_cb (GtkWidget * widget, GdkDragContext * context,
gint x, gint y, GtkSelectionData * data,
guint info, guint time, char *command)
{
GList *fnames, *fnp;
guint count;
char *execute;
fnames = gnome_uri_list_extract_filenames ((char *) data->data);
count = g_list_length (fnames);
if (count > 0)
{
execute = (char *) g_new0 (char, MAXSTRLEN);
strcpy (execute, command);
for (fnp = fnames; fnp; fnp = fnp->next, count--)
{
strcat (execute, " ");
strncat (execute, (char *) (fnp->data),
MAXSTRLEN - strlen (execute));
}
exec_cmd (execute);
g_free (execute);
hide_current_popup_menu ();
}
gnome_uri_list_free_strings (fnames);
gtk_drag_finish (context, (count > 0), (context->action == GDK_ACTION_MOVE),
time);
}
void
item_click_cb (GtkButton * b, char *command)
{
hide_current_popup_menu ();
exec_cmd (command);
}
gboolean
item_in_menu_press_cb (GtkButton * b, GdkEventButton * ev, PanelItem * pi)
{
if (ev->button != 3)
return FALSE;
edit_item_dlg (pi);
return TRUE;
}
gboolean
item_on_panel_press_cb (GtkButton * b, GdkEventButton * ev, PanelGroup * pg)
{
if (ev->button != 3)
return FALSE;
hide_current_popup_menu ();
edit_item_or_module_dlg (pg);
return TRUE;
}
/*****************************************************************************/

63
callbacks.h

@ -0,0 +1,63 @@
#ifndef __XFCE_CALLBACKS_H__
#define __XFCE_CALLBACKS_H__
#include <gtk/gtk.h>
#include "xfce.h"
/*****************************************************************************/
void exec_cmd (const char *cmd);
GList *gnome_uri_list_extract_filenames (const gchar * uri_list);
void gnome_uri_list_free_strings (GList * list);
/*****************************************************************************/
gboolean panel_delete_cb (GtkWidget * window, GdkEvent * ev, gpointer data);
/*****************************************************************************/
gboolean screen_button_pressed_cb (GtkButton * b, GdkEventButton * ev,
ScreenButton * sb);
void mini_lock_cb (char *cmd);
void mini_info_cb (void);
void mini_palet_cb (void);
void mini_power_cb (GtkButton * b, GdkEventButton * ev, gpointer data);
/*****************************************************************************/
void iconify_cb (void);
gboolean group_button_press_cb (GtkButton * b, GdkEventButton * ev,
PanelGroup * pg);
/*****************************************************************************/
void toggle_popup (GtkWidget * button, PanelPopup * pp);
void tearoff_popup (GtkWidget * button, PanelPopup * pp);
gboolean delete_popup (GtkWidget * window, GdkEvent * ev, PanelPopup * pp);
/*****************************************************************************/
void addtomenu_item_drop_cb (GtkWidget * widget, GdkDragContext * context,
gint x, gint y, GtkSelectionData * data,
guint info, guint time, PanelPopup * pp);
void addtomenu_item_click_cb (GtkButton * b, PanelPopup * pp);
void item_drop_cb (GtkWidget * widget, GdkDragContext * context,
gint x, gint y, GtkSelectionData * data,
guint info, guint time, char *command);
void item_click_cb (GtkButton * b, char *command);
gboolean item_in_menu_press_cb (GtkButton * b, GdkEventButton * ev,
PanelItem * pi);
gboolean item_on_panel_press_cb (GtkButton * b, GdkEventButton * ev,
PanelGroup * pg);
#endif /* __XFCE_CALLBACKS_H__ */

485
central.c

@ -0,0 +1,485 @@
#include <gtk/gtk.h>
#include "xfce.h"
#include "central.h"
#include "callbacks.h"
#include "icons.h"
/*****************************************************************************/
/* colors used for screen buttons in OLD_STYLE */
static char *screen_class[] = {
"gxfce_color2",
"gxfce_color5",
"gxfce_color4",
"gxfce_color6"
};
CentralPanel *
central_panel_new (void)
{
int i;
CentralPanel *cp = g_new (CentralPanel, 1);
cp->frame = NULL;
cp->hbox = NULL;
cp->left_table = NULL;
cp->left_buttons[0] = NULL;
cp->left_buttons[1] = NULL;
cp->right_table = NULL;
cp->right_buttons[0] = NULL;
cp->right_buttons[1] = NULL;
cp->desktop_table = NULL;
for (i = 0; i < NBSCREENS; i++)
{
cp->screen_buttons[i] = NULL;
cp->screen_names[i] = NULL;
}
cp->lock_command = NULL;
cp->xmlnode = NULL;
return cp;
}
static void
create_left_table (CentralPanel * cp)
{
GtkWidget *im;
GdkPixbuf *pb;
cp->left_table = gtk_table_new (2, 2, FALSE);
cp->left_buttons[0] = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (cp->left_buttons[0]), GTK_RELIEF_NONE);
cp->left_buttons[1] = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (cp->left_buttons[1]), GTK_RELIEF_NONE);
pb = get_pixbuf_from_id (MINILOCK_ICON);
im = gtk_image_new_from_pixbuf (pb);
g_object_unref (pb);
gtk_container_add (GTK_CONTAINER (cp->left_buttons[0]), im);
pb = get_pixbuf_from_id (MINIINFO_ICON);
im = gtk_image_new_from_pixbuf (pb);
g_object_unref (pb);
gtk_container_add (GTK_CONTAINER (cp->left_buttons[1]), im);
/* by default put buttons in 1st column in 2 rows */
gtk_table_attach (GTK_TABLE (cp->left_table), cp->left_buttons[0],
0, 1, 0, 1, GTK_SHRINK, GTK_EXPAND, 0, 0);
gtk_table_attach (GTK_TABLE (cp->left_table), cp->left_buttons[1],
0, 1, 1, 2, GTK_SHRINK, GTK_EXPAND, 0, 0);
gtk_widget_show_all (cp->left_table);
}
static void
create_right_table (CentralPanel * cp)
{
GtkWidget *im;
GdkPixbuf *pb;
cp->right_table = gtk_table_new (2, 2, FALSE);
cp->right_buttons[0] = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (cp->right_buttons[0]), GTK_RELIEF_NONE);
cp->right_buttons[1] = gtk_button_new ();
gtk_button_set_relief (GTK_BUTTON (cp->right_buttons[1]), GTK_RELIEF_NONE);
pb = get_pixbuf_from_id (MINIPALET_ICON);
im = gtk_image_new_from_pixbuf (pb);
g_object_unref (pb);
gtk_container_add (GTK_CONTAINER (cp->right_buttons[0]), im);
pb = get_pixbuf_from_id (MINIPOWER_ICON);
im = gtk_image_new_from_pixbuf (pb);
g_object_unref (pb);
gtk_container_add (GTK_CONTAINER (cp->right_buttons[1]), im);
/* by default put buttons in 1st column in 2 rows */
gtk_table_attach (GTK_TABLE (cp->right_table), cp->right_buttons[0],
0, 1, 0, 1, GTK_SHRINK, GTK_EXPAND, 0, 0);
gtk_table_attach (GTK_TABLE (cp->right_table), cp->right_buttons[1],
0, 1, 1, 2, GTK_SHRINK, GTK_EXPAND, 0, 0);
gtk_widget_show_all (cp->right_table);
}
static void
create_desktop_table (CentralPanel * cp)
{
int i;
cp->desktop_table = gtk_table_new (2, NBSCREENS, FALSE);
for (i = 0; i < NBSCREENS; i++)
{
ScreenButton *sb = cp->screen_buttons[i] = screen_button_new ();
sb->frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (sb->frame), GTK_SHADOW_IN);
sb->button = gtk_toggle_button_new ();
gtk_button_set_relief (GTK_BUTTON (sb->button), GTK_RELIEF_HALF);
gtk_widget_set_size_request (sb->button, SCREEN_BUTTON_WIDTH, -1);
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sb->button), i == 0);
gtk_container_add (GTK_CONTAINER (sb->frame), sb->button);
sb->label = gtk_label_new (cp->screen_names[i]);
gtk_misc_set_alignment (GTK_MISC (sb->label), 0.1, 0.5);
gtk_container_add (GTK_CONTAINER (sb->button), sb->label);
/* pack buttons alternating first and second row */
if ((i % 2) == 0)
{
gtk_table_attach (GTK_TABLE (cp->desktop_table), sb->frame,
i, i + 1, 0, 1, GTK_SHRINK, GTK_EXPAND, 0, 0);
}
else
{
int pos = i - 1;
gtk_table_attach (GTK_TABLE (cp->desktop_table), sb->frame,
pos, pos + 1, 1, 2, GTK_SHRINK, GTK_EXPAND, 0, 0);
}
/* signals */
/* we need the callback id to be able to block the handler to
prevent a race condition when changing screens */
sb->callback_id =
g_signal_connect_swapped (sb->button, "clicked",
G_CALLBACK (change_current_desktop),
GINT_TO_POINTER (i));
g_signal_connect (sb->button, "button-press-event",
G_CALLBACK (screen_button_pressed_cb), sb);
}
gtk_widget_show_all (cp->desktop_table);
}
void
add_central_panel (XfcePanel * p)
{
create_central_panel (p->central_panel);
gtk_box_pack_start (GTK_BOX (p->hbox), p->central_panel->frame,
TRUE, TRUE, 0);
}
void
create_central_panel (CentralPanel * cp)
{
cp->frame = gtk_frame_new (NULL);
gtk_frame_set_shadow_type (GTK_FRAME (cp->frame), GTK_SHADOW_OUT);
gtk_container_set_border_width (GTK_CONTAINER (cp->frame), 1);
cp->hbox = gtk_hbox_new (FALSE, 0);
gtk_container_add (GTK_CONTAINER (cp->frame), cp->hbox);
create_left_table (cp);
gtk_box_pack_start (GTK_BOX (cp->hbox), cp->left_table, FALSE, FALSE, 0);
create_desktop_table (cp);
gtk_box_pack_start (GTK_BOX (cp->hbox), cp->desktop_table, TRUE, TRUE, 0);
create_right_table (cp);
gtk_box_pack_start (GTK_BOX (cp->hbox), cp->right_table, FALSE, FALSE, 0);
gtk_widget_show (cp->hbox);
gtk_widget_show (cp->frame);
/* signals */
/* left minibuttons */
if (!cp->lock_command)
cp->lock_command = g_strdup ("xflock");
/* fixed tooltip, since the user can't change the icon anyway */
panel_set_tooltip (cp->left_buttons[0], _("Lock the screen"));
g_signal_connect_swapped (cp->left_buttons[0], "clicked",
G_CALLBACK (mini_lock_cb), cp->lock_command);
panel_set_tooltip (cp->left_buttons[1], _("Info..."));
g_signal_connect_swapped (cp->left_buttons[1], "clicked",
G_CALLBACK (mini_info_cb), NULL);
/* right minibuttons */
panel_set_tooltip (cp->right_buttons[0], _("Setup..."));
g_signal_connect_swapped (cp->right_buttons[0], "clicked",
G_CALLBACK (mini_palet_cb), NULL);
panel_set_tooltip (cp->right_buttons[1],
_("Mouse 1: Exit\nMouse 3: Restart"));
/* make left _and_ right button work */
g_signal_connect_swapped (cp->right_buttons[1], "button-press-event",
G_CALLBACK (gtk_button_pressed),
cp->right_buttons[1]);
g_signal_connect (cp->right_buttons[1], "button-release-event",
G_CALLBACK (mini_power_cb), NULL);
}
static int
get_screen_button_height (int size)
{
if (size == SMALL)
return SMALL_PANEL_ICONS;
else if (size == LARGE)
return (LARGE_TOPHEIGHT + LARGE_PANEL_ICONS) / 2 - 6;
else
return (MEDIUM_TOPHEIGHT + MEDIUM_PANEL_ICONS) / 2 - 5;
}
static int
get_screen_button_width (int size)
{
if (size == SMALL)
return SCREEN_BUTTON_WIDTH / 2;
else
return SCREEN_BUTTON_WIDTH;
}
void
central_panel_set_size (CentralPanel * cp, int size)
{
GtkRequisition req;
GList *child;
GtkTableChild *tc;
int hpos, vpos;
int h, w;
/* left table
when SMALL put second button in first column first row
else put second button in second column second row
*/
for (child = GTK_TABLE (cp->left_table)->children;
child && child->data; child = child->next)
{
tc = (GtkTableChild *) child->data;
if (tc->widget == cp->left_buttons [1])
break;
}
if (size == SMALL)
{
hpos = 1;
vpos = 0;
}
else
{
hpos = 0;
vpos = 1;
}
tc->left_attach = hpos;
tc->right_attach = hpos + 1;
tc->top_attach = vpos;
tc->bottom_attach = vpos + 1;
/* right table
when SMALL put second button in second column first row
else put second button in first column second row
*/
for (child = GTK_TABLE (cp->right_table)->children;
child && child->data; child = child->next)
{
tc = (GtkTableChild *) child->data;
if (tc->widget == cp->right_buttons [1])
break;
}
if (size == SMALL)
{
hpos = 1;
vpos = 0;
}
else
{
hpos = 0;
vpos = 1;
}
tc->left_attach = hpos;
tc->right_attach = hpos + 1;
tc->top_attach = vpos;
tc->bottom_attach = vpos + 1;
/* desktop table */
h = get_screen_button_height (size);
w = get_screen_button_width (size);
for (child = GTK_TABLE (cp->desktop_table)->children;
child && child->data; child = child->next)
{
ScreenButton *sb;
int i;
for (i = 0; i < NBSCREENS; i++)
{
sb = cp->screen_buttons[i];
gtk_widget_set_size_request (sb->button, w, h);
}
tc = (GtkTableChild *) child->data;
for (i = 0; i < NBSCREENS; i++)
{
sb = cp->screen_buttons[i];
if (tc->widget == sb->frame)
break;
}
if ((i % 2)==0)
{
if (size == SMALL)
{
hpos = i;
vpos = 0;
}
else
{
hpos = i / 2;
vpos = 0;
}
}
else
{
if (size == SMALL)
{
hpos = i;
vpos = 0;
}
else
{
hpos = (i - 1) / 2;
vpos = 1;
}
}