diff options
author | Richard Hult <richard@imendio.com> | 2003-08-24 16:29:20 +0000 |
---|---|---|
committer | Richard Hult <rhult@src.gnome.org> | 2003-08-24 16:29:20 +0000 |
commit | 05294ea9340370ade57d1766cfa75f81b868359d (patch) | |
tree | e662b21bc3ba0d032da4627f315f9c3505d3d4ed /typing-break | |
parent | 916e9dbc7598919e6c67c40f3f6e9dd57ae5bd21 (diff) | |
download | gnome-control-center-05294ea9340370ade57d1766cfa75f81b868359d.tar.gz |
Multihead support, fixes bug #119827.
2003-08-24 Richard Hult <richard@imendio.com>
* Makefile.am:
* drw-break-window.c:
* drwright.c: Multihead support, fixes bug #119827.
Diffstat (limited to 'typing-break')
-rw-r--r-- | typing-break/ChangeLog | 6 | ||||
-rw-r--r-- | typing-break/Makefile.am | 8 | ||||
-rw-r--r-- | typing-break/drw-break-window.c | 175 | ||||
-rw-r--r-- | typing-break/drw-utils.c | 173 | ||||
-rw-r--r-- | typing-break/drw-utils.h | 27 | ||||
-rw-r--r-- | typing-break/drwright.c | 154 | ||||
-rw-r--r-- | typing-break/egg-spawn.c | 355 | ||||
-rw-r--r-- | typing-break/egg-spawn.h | 81 |
8 files changed, 777 insertions, 202 deletions
diff --git a/typing-break/ChangeLog b/typing-break/ChangeLog index 00f35666d..0c2ef5106 100644 --- a/typing-break/ChangeLog +++ b/typing-break/ChangeLog @@ -1,3 +1,9 @@ +2003-08-24 Richard Hult <richard@imendio.com> + + * Makefile.am: + * drw-break-window.c: + * drwright.c: Multihead support, fixes bug #119827. + Thu Jul 31 17:41:45 2003 Jonathan Blandford <jrb@redhat.com> * drwright.c (popup_preferences_cb): add properties dialog, diff --git a/typing-break/Makefile.am b/typing-break/Makefile.am index a2280d841..28e72f31e 100644 --- a/typing-break/Makefile.am +++ b/typing-break/Makefile.am @@ -13,10 +13,14 @@ gnome_typing_monitor_SOURCES = \ drw-break-window.h \ drw-monitor.c \ drw-monitor.h \ + drw-utils.c \ + drw-utils.h \ + drw-selection.c \ + drw-selection.h \ eggtrayicon.c \ eggtrayicon.h \ - drw-selection.c \ - drw-selection.h + egg-spawn.c \ + egg-spawn.h gnome_typing_monitor_LDADD = @GNOME_LIBS@ -L/usr/X11R6/lib -lXss gnome_typing_monitor_LDFLAGS = -export-dynamic diff --git a/typing-break/drw-break-window.c b/typing-break/drw-break-window.c index 324e8dca9..1f7b5db38 100644 --- a/typing-break/drw-break-window.c +++ b/typing-break/drw-break-window.c @@ -1,7 +1,8 @@ /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ /* - * Copyright (C) 2002 CodeFactory AB - * Copyright (C) 2002 Richard Hult <richard@imendio.com> + * Copyright (C) 2002 CodeFactory AB + * Copyright (C) 2002-2003 Richard Hult <richard@imendio.com> + * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -27,9 +28,9 @@ #include <gconf/gconf-client.h> #include <libgnome/gnome-i18n.h> #include "drwright.h" +#include "drw-utils.h" #include "drw-break-window.h" - struct _DrwBreakWindowPriv { GtkWidget *clock_label; GtkWidget *break_label; @@ -59,11 +60,7 @@ enum { static void drw_break_window_class_init (DrwBreakWindowClass *klass); static void drw_break_window_init (DrwBreakWindow *window); static void drw_break_window_finalize (GObject *object); -static GdkPixbuf * create_tile_pixbuf (GdkPixbuf *dest_pixbuf, - GdkPixbuf *src_pixbuf, - GdkRectangle *field_geom, - guint alpha, - GdkColor *bg_color); +static void drw_break_window_dispose (GObject *object); static gboolean clock_timeout_cb (DrwBreakWindow *window); static void postpone_clicked_cb (GtkWidget *button, GtkWidget *window); @@ -113,6 +110,7 @@ drw_break_window_class_init (DrwBreakWindowClass *klass) parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass)); object_class->finalize = drw_break_window_finalize; + object_class->dispose = drw_break_window_dispose; signals[POSTPONE] = g_signal_new ("postpone", @@ -142,10 +140,6 @@ drw_break_window_init (DrwBreakWindow *window) GtkWidget *frame; GtkWidget *align; gchar *str; - GdkPixbuf *tmp_pixbuf, *pixbuf, *tile_pixbuf; - GdkPixmap *pixmap; - GdkRectangle rect; - GdkColor color; GtkWidget *outer_vbox; GtkWidget *button_box; gboolean allow_postpone; @@ -170,72 +164,7 @@ drw_break_window_init (DrwBreakWindow *window) gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE); gtk_widget_realize (GTK_WIDGET (window)); - tmp_pixbuf = gdk_pixbuf_get_from_drawable (NULL, - gdk_get_default_root_window (), - gdk_colormap_get_system (), - 0, - 0, - 0, - 0, - gdk_screen_width (), - gdk_screen_height ()); - - pixbuf = gdk_pixbuf_new_from_file (IMAGEDIR "/ocean-stripes.png", NULL); - - rect.x = 0; - rect.y = 0; - rect.width = gdk_screen_width (); - rect.height = gdk_screen_height (); - - color.red = 0; - color.blue = 0; - color.green = 0; - - tile_pixbuf = create_tile_pixbuf (NULL, - pixbuf, - &rect, - 155, - &color); - - g_object_unref (pixbuf); - - gdk_pixbuf_composite (tile_pixbuf, - tmp_pixbuf, - 0, - 0, - gdk_screen_width (), - gdk_screen_height (), - 0, - 0, - 1, - 1, - GDK_INTERP_NEAREST, - 225); - - g_object_unref (tile_pixbuf); - - pixmap = gdk_pixmap_new (GTK_WIDGET (window)->window, - gdk_screen_width (), - gdk_screen_height (), - -1); - - gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf, - pixmap, - 0, - 0, - 0, - 0, - gdk_screen_width (), - gdk_screen_height (), - GDK_PIXBUF_ALPHA_BILEVEL, - 0, - GDK_RGB_DITHER_NONE, - 0, - 0); - g_object_unref (tmp_pixbuf); - - gdk_window_set_back_pixmap (GTK_WIDGET (window)->window, pixmap, FALSE); - g_object_unref (pixmap); + drw_setup_background (GTK_WIDGET (window)); frame = gtk_frame_new (NULL); gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_NONE); @@ -361,77 +290,33 @@ drw_break_window_finalize (GObject *object) } } -GtkWidget * -drw_break_window_new (void) +static void +drw_break_window_dispose (GObject *object) { - return g_object_new (DRW_TYPE_BREAK_WINDOW, NULL); -} + DrwBreakWindow *window = DRW_BREAK_WINDOW (object); + DrwBreakWindowPriv *priv; + + priv = window->priv; -static GdkPixbuf * -create_tile_pixbuf (GdkPixbuf *dest_pixbuf, - GdkPixbuf *src_pixbuf, - GdkRectangle *field_geom, - guint alpha, - GdkColor *bg_color) -{ - gboolean need_composite; - gboolean use_simple; - gdouble cx, cy; - gdouble colorv; - gint pwidth, pheight; - - need_composite = (alpha < 255 || gdk_pixbuf_get_has_alpha (src_pixbuf)); - use_simple = (dest_pixbuf == NULL); - - if (dest_pixbuf == NULL) - dest_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, field_geom->width, field_geom->height); - - if (need_composite && use_simple) - colorv = ((bg_color->red & 0xff00) << 8) | - (bg_color->green & 0xff00) | - ((bg_color->blue & 0xff00) >> 8); - else - colorv = 0; - - pwidth = gdk_pixbuf_get_width (src_pixbuf); - pheight = gdk_pixbuf_get_height (src_pixbuf); - - for (cy = 0; cy < field_geom->height; cy += pheight) { - for (cx = 0; cx < field_geom->width; cx += pwidth) { - if (need_composite && !use_simple) - gdk_pixbuf_composite - (src_pixbuf, dest_pixbuf, - cx, cy, - MIN (pwidth, field_geom->width - cx), - MIN (pheight, field_geom->height - cy), - cx, cy, - 1.0, 1.0, - GDK_INTERP_BILINEAR, - alpha); - else if (need_composite && use_simple) - gdk_pixbuf_composite_color - (src_pixbuf, dest_pixbuf, - cx, cy, - MIN (pwidth, field_geom->width - cx), - MIN (pheight, field_geom->height - cy), - cx, cy, - 1.0, 1.0, - GDK_INTERP_BILINEAR, - alpha, - 65536, 65536, 65536, - colorv, colorv); - else - gdk_pixbuf_copy_area - (src_pixbuf, - 0, 0, - MIN (pwidth, field_geom->width - cx), - MIN (pheight, field_geom->height - cy), - dest_pixbuf, - cx, cy); - } + if (priv->clock_timeout_id != 0) { + g_source_remove (priv->clock_timeout_id); + priv->clock_timeout_id = 0; + } + + if (priv->postpone_timeout_id != 0) { + g_source_remove (priv->postpone_timeout_id); + priv->postpone_timeout_id = 0; } - return dest_pixbuf; + if (G_OBJECT_CLASS (parent_class)->dispose) { + (* G_OBJECT_CLASS (parent_class)->dispose) (object); + } +} + +GtkWidget * +drw_break_window_new (void) +{ + return g_object_new (DRW_TYPE_BREAK_WINDOW, NULL); } static gboolean diff --git a/typing-break/drw-utils.c b/typing-break/drw-utils.c new file mode 100644 index 000000000..10db6aee7 --- /dev/null +++ b/typing-break/drw-utils.c @@ -0,0 +1,173 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Richard Hult <richard@imendio.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include <config.h> +#include <gdk/gdk.h> +#include <gtk/gtk.h> +#include "drw-utils.h" + +static GdkPixbuf * +create_tile_pixbuf (GdkPixbuf *dest_pixbuf, + GdkPixbuf *src_pixbuf, + GdkRectangle *field_geom, + guint alpha, + GdkColor *bg_color) +{ + gboolean need_composite; + gboolean use_simple; + gdouble cx, cy; + gdouble colorv; + gint pwidth, pheight; + + need_composite = (alpha < 255 || gdk_pixbuf_get_has_alpha (src_pixbuf)); + use_simple = (dest_pixbuf == NULL); + + if (dest_pixbuf == NULL) + dest_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, + FALSE, 8, + field_geom->width, field_geom->height); + + if (need_composite && use_simple) + colorv = ((bg_color->red & 0xff00) << 8) | + (bg_color->green & 0xff00) | + ((bg_color->blue & 0xff00) >> 8); + else + colorv = 0; + + pwidth = gdk_pixbuf_get_width (src_pixbuf); + pheight = gdk_pixbuf_get_height (src_pixbuf); + + for (cy = 0; cy < field_geom->height; cy += pheight) { + for (cx = 0; cx < field_geom->width; cx += pwidth) { + if (need_composite && !use_simple) + gdk_pixbuf_composite (src_pixbuf, dest_pixbuf, + cx, cy, + MIN (pwidth, field_geom->width - cx), + MIN (pheight, field_geom->height - cy), + cx, cy, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + alpha); + else if (need_composite && use_simple) + gdk_pixbuf_composite_color (src_pixbuf, dest_pixbuf, + cx, cy, + MIN (pwidth, field_geom->width - cx), + MIN (pheight, field_geom->height - cy), + cx, cy, + 1.0, 1.0, + GDK_INTERP_BILINEAR, + alpha, + 65536, 65536, 65536, + colorv, colorv); + else + gdk_pixbuf_copy_area (src_pixbuf, + 0, 0, + MIN (pwidth, field_geom->width - cx), + MIN (pheight, field_geom->height - cy), + dest_pixbuf, + cx, cy); + } + } + + return dest_pixbuf; +} + +void +drw_setup_background (GtkWidget *window) +{ + GdkScreen *screen; + GdkPixbuf *tmp_pixbuf, *pixbuf, *tile_pixbuf; + GdkPixmap *pixmap; + GdkRectangle rect; + GdkColor color; + gint width, height; + + screen = gtk_widget_get_screen (window); + + width = gdk_screen_get_width (screen); + height = gdk_screen_get_height (screen); + + tmp_pixbuf = gdk_pixbuf_get_from_drawable (NULL, + gdk_screen_get_root_window (screen), + gdk_screen_get_system_colormap (screen), + 0, + 0, + 0, + 0, + width, height); + + pixbuf = gdk_pixbuf_new_from_file (IMAGEDIR "/ocean-stripes.png", NULL); + + rect.x = 0; + rect.y = 0; + rect.width = width; + rect.height = height; + + color.red = 0; + color.blue = 0; + color.green = 0; + + tile_pixbuf = create_tile_pixbuf (NULL, + pixbuf, + &rect, + 155, + &color); + + g_object_unref (pixbuf); + + gdk_pixbuf_composite (tile_pixbuf, + tmp_pixbuf, + 0, + 0, + width, + height, + 0, + 0, + 1, + 1, + GDK_INTERP_NEAREST, + 225); + + g_object_unref (tile_pixbuf); + + pixmap = gdk_pixmap_new (GTK_WIDGET (window)->window, + width, + height, + -1); + + gdk_pixbuf_render_to_drawable_alpha (tmp_pixbuf, + pixmap, + 0, + 0, + 0, + 0, + width, + height, + GDK_PIXBUF_ALPHA_BILEVEL, + 0, + GDK_RGB_DITHER_NONE, + 0, + 0); + g_object_unref (tmp_pixbuf); + + gdk_window_set_back_pixmap (window->window, pixmap, FALSE); + g_object_unref (pixmap); +} + diff --git a/typing-break/drw-utils.h b/typing-break/drw-utils.h new file mode 100644 index 000000000..968f531fd --- /dev/null +++ b/typing-break/drw-utils.h @@ -0,0 +1,27 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * Copyright (C) 2003 Richard Hult <richard@imendio.com> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __DRW_UTILS_H__ +#define __DRW_UTILS_H__ + +void drw_setup_background (GtkWidget *window); + + +#endif /* __DRW_UTILS_H__ */ diff --git a/typing-break/drwright.c b/typing-break/drwright.c index 9c9d78343..5afb1faa8 100644 --- a/typing-break/drwright.c +++ b/typing-break/drwright.c @@ -33,7 +33,9 @@ #include "drwright.h" #include "drw-break-window.h" #include "drw-monitor.h" +#include "drw-utils.h" #include "eggtrayicon.h" +#include "egg-spawn.h" #define BLINK_TIMEOUT 200 #define BLINK_TIMEOUT_MIN 120 @@ -57,7 +59,8 @@ typedef enum { struct _DrWright { /* Widgets. */ GtkWidget *break_window; - + GList *secondary_break_windows; + DrwMonitor *monitor; GtkItemFactory *popup_factory; @@ -96,34 +99,33 @@ struct _DrWright { GtkWidget *warn_dialog; }; -static void activity_detected_cb (DrwMonitor *monitor, - DrWright *drwright); -static gboolean maybe_change_state (DrWright *drwright); -static gboolean update_tooltip (DrWright *drwright); -static gboolean icon_button_press_cb (GtkWidget *widget, - GdkEventButton *event, - DrWright *drwright); -static void break_window_done_cb (GtkWidget *window, - DrWright *dr); -static void break_window_postpone_cb (GtkWidget *window, - DrWright *dr); -#if 0 -static void popup_enabled_cb (gpointer callback_data, - guint action, - GtkWidget *widget); -#endif -static void popup_break_cb (gpointer callback_data, - guint action, - GtkWidget *widget); -static void popup_preferences_cb (gpointer callback_data, - guint action, - GtkWidget *widget); -static void popup_about_cb (gpointer callback_data, - guint action, - GtkWidget *widget); -static gchar * item_factory_trans_cb (const gchar *path, - gpointer data); -static void init_tray_icon (DrWright *dr); +static void activity_detected_cb (DrwMonitor *monitor, + DrWright *drwright); +static gboolean maybe_change_state (DrWright *drwright); +static gboolean update_tooltip (DrWright *drwright); +static gboolean icon_button_press_cb (GtkWidget *widget, + GdkEventButton *event, + DrWright *drwright); +static void break_window_done_cb (GtkWidget *window, + DrWright *dr); +static void break_window_postpone_cb (GtkWidget *window, + DrWright *dr); +static void break_window_destroy_cb (GtkWidget *window, + DrWright *dr); +static void popup_break_cb (gpointer callback_data, + guint action, + GtkWidget *widget); +static void popup_preferences_cb (gpointer callback_data, + guint action, + GtkWidget *widget); +static void popup_about_cb (gpointer callback_data, + guint action, + GtkWidget *widget); +static gchar * item_factory_trans_cb (const gchar *path, + gpointer data); +static void init_tray_icon (DrWright *dr); +static GList * create_secondary_break_windows (void); + #define GIF_CB(x) ((GtkItemFactoryCallback)(x)) @@ -390,6 +392,13 @@ maybe_change_state (DrWright *dr) G_CALLBACK (break_window_postpone_cb), dr); + g_signal_connect (dr->break_window, + "destroy", + G_CALLBACK (break_window_destroy_cb), + dr); + + dr->secondary_break_windows = create_secondary_break_windows (); + gtk_widget_show (dr->break_window); dr->state = STATE_BREAK; @@ -525,27 +534,6 @@ gconf_notify_cb (GConfClient *client, maybe_change_state (dr); } -#if 0 -static void -popup_enabled_cb (gpointer callback_data, - guint action, - GtkWidget *widget) -{ - DrWright *dr = callback_data; - GtkWidget *item; - gboolean enabled; - - item = gtk_item_factory_get_widget_by_action (dr->popup_factory, - POPUP_ITEM_ENABLED); - - enabled = gtk_check_menu_item_get_active (GTK_CHECK_MENU_ITEM (item)); - - gconf_client_set_bool (client, GCONF_PATH "/enabled", - enabled, - NULL); -} -#endif - static void popup_break_cb (gpointer callback_data, guint action, @@ -564,10 +552,12 @@ popup_preferences_cb (gpointer callback_data, guint action, GtkWidget *widget) { - GError *error = NULL; + GdkScreen *screen; + GError *error = NULL; - /* FIXME: Needs multi-head/screen support */ - if (!g_spawn_command_line_async ("gnome-keyboard-properties --typing-break", &error)) { + screen = gtk_widget_get_screen (widget); + + if (!egg_spawn_command_line_async_on_screen ("gnome-keyboard-properties --typing-break", screen, &error)) { GtkWidget *error_dialog; error_dialog = gtk_message_dialog_new (NULL, 0, @@ -575,12 +565,12 @@ popup_preferences_cb (gpointer callback_data, GTK_BUTTONS_CLOSE, _("Unable to bring up the typing break properties dialog with the following error: %s"), error->message); - g_signal_connect (G_OBJECT (error_dialog), + g_signal_connect (error_dialog, "response", G_CALLBACK (gtk_widget_destroy), NULL); gtk_window_set_resizable (GTK_WINDOW (error_dialog), FALSE); gtk_widget_show (error_dialog); - + g_error_free (error); } } @@ -753,6 +743,20 @@ break_window_postpone_cb (GtkWidget *window, update_tooltip (dr); } +static void +break_window_destroy_cb (GtkWidget *window, + DrWright *dr) +{ + GList *l; + + for (l = dr->secondary_break_windows; l; l = l->next) { + gtk_widget_destroy (l->data); + } + + g_list_free (dr->secondary_break_windows); + dr->secondary_break_windows = NULL; +} + static char * item_factory_trans_cb (const gchar *path, gpointer data) @@ -834,6 +838,46 @@ init_tray_icon (DrWright *dr) dr); } +static GList * +create_secondary_break_windows (void) +{ + GdkDisplay *display; + GdkScreen *screen; + GtkWidget *window; + gint i; + GList *windows = NULL; + + display = gdk_display_get_default (); + + for (i = 0; i < gdk_display_get_n_screens (display); i++) { + screen = gdk_display_get_screen (display, i); + + if (screen == gdk_screen_get_default ()) { + /* Handled by DrwBreakWindow. */ + continue; + } + + window = gtk_window_new (GTK_WINDOW_POPUP); + + windows = g_list_prepend (windows, window); + + gtk_window_set_screen (GTK_WINDOW (window), screen); + + gtk_window_set_default_size (GTK_WINDOW (window), + gdk_screen_get_width (screen), + gdk_screen_get_height (screen)); + + gtk_widget_set_app_paintable (GTK_WIDGET (window), TRUE); + gtk_widget_realize (GTK_WIDGET (window)); + + drw_setup_background (GTK_WIDGET (window)); + gtk_window_stick (GTK_WINDOW (window)); + gtk_widget_show (window); + } + + return windows; +} + DrWright * drwright_new (void) { diff --git a/typing-break/egg-spawn.c b/typing-break/egg-spawn.c new file mode 100644 index 000000000..a1e0389b5 --- /dev/null +++ b/typing-break/egg-spawn.c @@ -0,0 +1,355 @@ +/* egg-spawn.c: + * + * Copyright (C) 2002 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Mark McLoughlin <mark@skynet.ie> + */ + +#include <config.h> +#include <string.h> + +#include "egg-spawn.h" + +#include <glib.h> +#include <gdk/gdk.h> + +extern char **environ; + +/** + * egg_make_spawn_environment_for_screen: + * @screen: A #GdkScreen + * @envp: program environment to copy, or NULL to use current environment. + * + * Returns a modified copy of the program environment @envp (or the current + * environment if @envp is NULL) with $DISPLAY set such that a launched + * application (which calls gdk_display_open()) inheriting this environment + * would have @screen as its default screen.. + * + * Returns: a newly-allocated %NULL-terminated array of strings or + * %NULL on error. Use g_strfreev() to free it. + **/ +gchar ** +egg_make_spawn_environment_for_screen (GdkScreen *screen, + gchar **envp) +{ + gchar **retval = NULL; + gchar *display_name; + gint display_index = -1; + gint i, env_len; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), NULL); + + if (envp == NULL) + envp = environ; + + for (env_len = 0; envp [env_len]; env_len++) + if (!strncmp (envp [env_len], "DISPLAY", strlen ("DISPLAY"))) + display_index = env_len; + + if (display_index == -1) + display_index = env_len++; + + retval = g_new (char *, env_len + 1); + retval [env_len] = NULL; + + display_name = gdk_screen_make_display_name (screen); + + for (i = 0; i < env_len; i++) + if (i == display_index) + retval [i] = g_strconcat ("DISPLAY=", display_name, NULL); + else + retval [i] = g_strdup (envp [i]); + + g_assert (i == env_len); + + g_free (display_name); + + return retval; +} + +/** + * egg_spawn_async_on_screen: + * @working_directory: child's current working directory, or %NULL to inherit parent's + * @argv: child's argument vector + * @envp: child's environment, or %NULL to inherit parent's + * @flags: flags from #GSpawnFlags + * @child_setup: function to run in the child just before <function>exec()</function> + * @user_data: user data for @child_setup + * @screen: a #GdkScreen + * @child_pid: return location for child process ID, or %NULL + * @error: return location for error + * + * Like g_spawn_async(), except the child process is spawned in such + * an environment that on calling gdk_display_open() it would be + * returned a #GdkDisplay with @screen as the default screen. + * + * This is useful for applications which wish to launch an application + * on a specific screen. + * + * Return value: %TRUE on success, %FALSE if error is set + **/ +gboolean +egg_spawn_async_on_screen (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GdkScreen *screen, + gint *child_pid, + GError **error) +{ + GdkScreen *default_screen; + gchar **new_envp = NULL; + gboolean retval; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + default_screen = gdk_display_get_default_screen ( + gdk_screen_get_display (screen)); + if (screen != default_screen) + new_envp = egg_make_spawn_environment_for_screen (screen, envp); + + retval = g_spawn_async (working_directory, argv, + new_envp ? new_envp : envp, + flags, child_setup, user_data, + child_pid, error); + + g_strfreev (new_envp); + + return retval; +} + +/** + * egg_spawn_async_with_pipes_on_screen: + * @working_directory: child's current working directory, or %NULL to inherit parent's + * @argv: child's argument vector + * @envp: child's environment, or %NULL to inherit parent's + * @flags: flags from #GSpawnFlags + * @child_setup: function to run in the child just before <function>exec()</function> + * @user_data: user data for @child_setup + * @screen: a #GdkScreen + * @child_pid: return location for child process ID, or %NULL + * @standard_input: return location for file descriptor to write to child's stdin, or %NULL + * @standard_output: return location for file descriptor to read child's stdout, or %NULL + * @standard_error: return location for file descriptor to read child's stderr, or %NULL + * @error: return location for error + * + * Like g_spawn_async_with_pipes(), except the child process is + * spawned in such an environment that on calling gdk_display_open() + * it would be returned a #GdkDisplay with @screen as the default + * screen. + * + * This is useful for applications which wish to launch an application + * on a specific screen. + * + * Return value: %TRUE on success, %FALSE if an error was set + **/ +gboolean +egg_spawn_async_with_pipes_on_screen (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GdkScreen *screen, + gint *child_pid, + gint *standard_input, + gint *standard_output, + gint *standard_error, + GError **error) +{ + GdkScreen *default_screen; + gchar **new_envp = NULL; + gboolean retval; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + default_screen = gdk_display_get_default_screen ( + gdk_screen_get_display (screen)); + if (screen != default_screen) + new_envp = egg_make_spawn_environment_for_screen (screen, envp); + + retval = g_spawn_async_with_pipes (working_directory, argv, + new_envp ? new_envp : envp, + flags, child_setup, user_data, + child_pid, standard_input, + standard_output, standard_error, + error); + + g_strfreev (new_envp); + + return retval; +} + +/** + * egg_spawn_sync_on_screen: + * @working_directory: child's current working directory, or %NULL to inherit parent's + * @argv: child's argument vector + * @envp: child's environment, or %NULL to inherit parent's + * @flags: flags from #GSpawnFlags + * @child_setup: function to run in the child just before <function>exec()</function> + * @user_data: user data for @child_setup + * @screen: a #GdkScreen + * @standard_output: return location for child output + * @standard_error: return location for child error messages + * @exit_status: child exit status, as returned by <function>waitpid()</function> + * @error: return location for error + * + * Like g_spawn_sync(), except the child process is spawned in such + * an environment that on calling gdk_display_open() it would be + * returned a #GdkDisplay with @screen as the default screen. + * + * This is useful for applications which wish to launch an application + * on a specific screen. + * + * Return value: %TRUE on success, %FALSE if an error was set. + **/ +gboolean +egg_spawn_sync_on_screen (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GdkScreen *screen, + gchar **standard_output, + gchar **standard_error, + gint *exit_status, + GError **error) +{ + GdkScreen *default_screen; + gchar **new_envp = NULL; + gboolean retval; + + g_return_val_if_fail (GDK_IS_SCREEN (screen), FALSE); + + default_screen = gdk_display_get_default_screen ( + gdk_screen_get_display (screen)); + if (screen != default_screen) + new_envp = egg_make_spawn_environment_for_screen (screen, envp); + + retval = g_spawn_sync (working_directory, argv, + new_envp ? new_envp : envp, + flags, child_setup, user_data, + standard_output, standard_error, + exit_status, error); + + g_strfreev (new_envp); + + return retval; +} + +/** + * egg_spawn_command_line_sync_on_screen: + * @command_line: a command line + * @screen: a #GdkScreen + * @standard_output: return location for child output + * @standard_error: return location for child errors + * @exit_status: return location for child exit status + * @error: return location for errors + * + * Like g_spawn_command_line_sync(), except the child process is + * spawned in such an environment that on calling gdk_display_open() + * it would be returned a #GdkDisplay with @screen as the default + * screen. + * + * This is useful for applications which wish to launch an application + * on a specific screen. + * + * Return value: %TRUE on success, %FALSE if an error was set + **/ +gboolean +egg_spawn_command_line_sync_on_screen (const gchar *command_line, + GdkScreen *screen, + gchar **standard_output, + gchar **standard_error, + gint *exit_status, + GError **error) +{ + gchar **argv = NULL; + gboolean retval; + + g_return_val_if_fail (command_line != NULL, FALSE); + + if (!g_shell_parse_argv (command_line, + NULL, &argv, + error)) + return FALSE; + + retval = egg_spawn_sync_on_screen (NULL, + argv, + NULL, + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + screen, + standard_output, + standard_error, + exit_status, + error); + + g_strfreev (argv); + + return retval; +} + +/** + * egg_spawn_command_line_async_on_screen: + * @command_line: a command line + * @screen: a #GdkScreen + * @error: return location for errors + * + * Like g_spawn_command_line_async(), except the child process is + * spawned in such an environment that on calling gdk_display_open() + * it would be returned a #GdkDisplay with @screen as the default + * screen. + * + * This is useful for applications which wish to launch an application + * on a specific screen. + * + * Return value: %TRUE on success, %FALSE if error is set. + **/ +gboolean +egg_spawn_command_line_async_on_screen (const gchar *command_line, + GdkScreen *screen, + GError **error) +{ + gchar **argv = NULL; + gboolean retval; + + g_return_val_if_fail (command_line != NULL, FALSE); + + if (!g_shell_parse_argv (command_line, + NULL, &argv, + error)) + return FALSE; + + retval = egg_spawn_async_on_screen (NULL, + argv, + NULL, + G_SPAWN_SEARCH_PATH, + NULL, + NULL, + screen, + NULL, + error); + g_strfreev (argv); + + return retval; +} diff --git a/typing-break/egg-spawn.h b/typing-break/egg-spawn.h new file mode 100644 index 000000000..478fa2a70 --- /dev/null +++ b/typing-break/egg-spawn.h @@ -0,0 +1,81 @@ +/* egg-spawn.h: + * + * Copyright (C) 2002 Sun Microsystems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * Authors: Mark McLoughlin <mark@skynet.ie> + */ + +#ifndef __EGG_SPAWN_H__ +#define __EGG_SPAWN_H__ + +#include <gdk/gdk.h> +#include <glib/gspawn.h> + +G_BEGIN_DECLS + +gchar **egg_make_spawn_environment_for_screen (GdkScreen *screen, + gchar **envp); + +gboolean egg_spawn_async_on_screen (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GdkScreen *screen, + gint *child_pid, + GError **error); + +gboolean egg_spawn_async_with_pipes_on_screen (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GdkScreen *screen, + gint *child_pid, + gint *standard_input, + gint *standard_output, + gint *standard_error, + GError **error); + +gboolean egg_spawn_sync_on_screen (const gchar *working_directory, + gchar **argv, + gchar **envp, + GSpawnFlags flags, + GSpawnChildSetupFunc child_setup, + gpointer user_data, + GdkScreen *screen, + gchar **standard_output, + gchar **standard_error, + gint *exit_status, + GError **error); + +gboolean egg_spawn_command_line_sync_on_screen (const gchar *command_line, + GdkScreen *screen, + gchar **standard_output, + gchar **standard_error, + gint *exit_status, + GError **error); +gboolean egg_spawn_command_line_async_on_screen (const gchar *command_line, + GdkScreen *screen, + GError **error); + +G_END_DECLS + +#endif /* __EGG_SPAWN_H__ */ |