summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2001-10-24 23:14:18 +0000
committerHavoc Pennington <hp@src.gnome.org>2001-10-24 23:14:18 +0000
commit1b33f9f46721f82a42d99cd4cd2947e95b3f8f50 (patch)
tree5682d207372228c76ebe302ab878aeb896236556
parentbd2798a0d5ade9f73bba408ae2353348a2858a74 (diff)
downloadlibwnck-1b33f9f46721f82a42d99cd4cd2947e95b3f8f50.tar.gz
hack to work with slightly older GTK as well as HEAD
2001-10-24 Havoc Pennington <hp@redhat.com> * configure.in: hack to work with slightly older GTK as well as HEAD * libwnck/screen.c (wnck_screen_force_update): add function to force immediate reading of screen state, instead of queueing it * libwnck/window.c: add geometry reporting * libwnck/pager.c: pager widget skeleton
-rw-r--r--ChangeLog12
-rw-r--r--configure.in6
-rw-r--r--libwnck/Makefile.am9
-rw-r--r--libwnck/application.c5
-rw-r--r--libwnck/libwnck.h3
-rw-r--r--libwnck/pager.c355
-rw-r--r--libwnck/pager.h64
-rw-r--r--libwnck/private.h3
-rw-r--r--libwnck/screen.c61
-rw-r--r--libwnck/screen.h4
-rw-r--r--libwnck/test-pager.c61
-rw-r--r--libwnck/test-wnck.c19
-rw-r--r--libwnck/util.c42
-rw-r--r--libwnck/util.h31
-rw-r--r--libwnck/window.c92
-rw-r--r--libwnck/window.h9
-rw-r--r--libwnck/workspace.c24
-rw-r--r--libwnck/workspace.h2
-rw-r--r--libwnck/xutils.c119
-rw-r--r--libwnck/xutils.h15
20 files changed, 916 insertions, 20 deletions
diff --git a/ChangeLog b/ChangeLog
index 9bf4ed6..3e5e7b0 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,15 @@
+2001-10-24 Havoc Pennington <hp@redhat.com>
+
+ * configure.in: hack to work with slightly older GTK as well as
+ HEAD
+
+ * libwnck/screen.c (wnck_screen_force_update): add function to
+ force immediate reading of screen state, instead of queueing it
+
+ * libwnck/window.c: add geometry reporting
+
+ * libwnck/pager.c: pager widget skeleton
+
2001-10-18 Havoc Pennington <hp@redhat.com>
* libwnck/tasklist.c: skeleton of widget for tasklist-like
diff --git a/configure.in b/configure.in
index aaa901e..7f2cc65 100644
--- a/configure.in
+++ b/configure.in
@@ -73,6 +73,12 @@ fi
AC_SUBST(GDK_PIXBUF_CSOURCE)
+## hack to work with old GTK versions for now
+save_LDFLAGS=$LDFLAGS
+LDFLAGS="$LIBWNCK_LIBS $LDFLAGS"
+AC_CHECK_FUNCS(gdk_pixbuf_new_from_stream)
+LDFLAGS=$save_LDFLAGS
+
AC_OUTPUT([
Makefile
libwnck/Makefile
diff --git a/libwnck/Makefile.am b/libwnck/Makefile.am
index b0b04d7..cb36a0f 100644
--- a/libwnck/Makefile.am
+++ b/libwnck/Makefile.am
@@ -7,9 +7,11 @@ lib_LTLIBRARIES=libwnck-1.la
libwnckincludedir=$(includedir)/libwnck-1.0/libwnck
wnck_headers= \
libwnck.h \
+ pager.h \
application.h \
screen.h \
tasklist.h \
+ util.h \
window.h \
window-action-menu.h \
window-menu.h \
@@ -27,9 +29,11 @@ wnck_built_cfiles = wnck-enum-types.c wnck-marshal.c
libwnck_1_la_SOURCES= \
application.c \
inlinepixbufs.h \
+ pager.c \
private.h \
screen.c \
tasklist.c \
+ util.c \
window.c \
window-action-menu.c \
window-menu.c \
@@ -45,7 +49,11 @@ test_wnck_SOURCES= \
test_tasklist_SOURCES= \
test-tasklist.c
+test_pager_SOURCES= \
+ test-pager.c
+
noinst_PROGRAMS= \
+ test-pager \
test-wnck \
test-tasklist
@@ -58,6 +66,7 @@ libwnck_1_la_LIBADD= \
test_wnck_LDADD=@LIBWNCK_LIBS@ libwnck-1.la
test_tasklist_LDADD=@LIBWNCK_LIBS@ libwnck-1.la
+test_pager_LDADD=@LIBWNCK_LIBS@ libwnck-1.la
## we just punt on built sources, and check them into cvs, manually updating
## when required.
diff --git a/libwnck/application.c b/libwnck/application.c
index 0be4e81..eee28f1 100644
--- a/libwnck/application.c
+++ b/libwnck/application.c
@@ -152,13 +152,12 @@ _wnck_application_create (Window xwindow,
/* Hash now owns one ref, caller gets none */
/* Note that xwindow may correspond to a WnckWindow's xwindow,
- * right now it doesn't matter since we use PropertyChangeMask
- * both places
+ * so we select events needed by either
*/
_wnck_error_trap_push ();
XSelectInput (gdk_display,
application->priv->xwindow,
- PropertyChangeMask);
+ WNCK_APP_WINDOW_EVENT_MASK);
_wnck_error_trap_pop ();
return application;
diff --git a/libwnck/libwnck.h b/libwnck/libwnck.h
index 261221c..fb9c013 100644
--- a/libwnck/libwnck.h
+++ b/libwnck/libwnck.h
@@ -24,10 +24,13 @@
#include <libwnck/application.h>
#include <libwnck/screen.h>
+#include <libwnck/util.h>
#include <libwnck/window.h>
#include <libwnck/workspace.h>
#include <libwnck/wnck-enum-types.h>
+#include <libwnck/pager.h>
+#include <libwnck/tasklist.h>
#include <libwnck/window-menu.h>
#endif /* WNCK_LIB_H */
diff --git a/libwnck/pager.c b/libwnck/pager.c
new file mode 100644
index 0000000..2fd94c5
--- /dev/null
+++ b/libwnck/pager.c
@@ -0,0 +1,355 @@
+/* pager object */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *
+ * 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.
+ */
+
+#include "pager.h"
+#include "workspace.h"
+
+#define MIN_WORKSPACE_SIZE 8
+
+struct _WnckPagerPrivate
+{
+ WnckScreen *screen;
+ int n_rows; /* really columns for vertical orientation */
+ GtkOrientation orientation;
+};
+
+enum
+{
+ LAST_SIGNAL
+};
+
+static void wnck_pager_init (WnckPager *pager);
+static void wnck_pager_class_init (WnckPagerClass *klass);
+static void wnck_pager_finalize (GObject *object);
+
+static void wnck_pager_realize (GtkWidget *widget);
+static void wnck_pager_unrealize (GtkWidget *widget);
+static void wnck_pager_size_request (GtkWidget *widget,
+ GtkRequisition *requisition);
+static void wnck_pager_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation);
+static gboolean wnck_pager_expose_event (GtkWidget *widget,
+ GdkEventExpose *event);
+static gboolean wnck_pager_button_press (GtkWidget *widget,
+ GdkEventButton *event);
+static gboolean wnck_pager_focus (GtkWidget *widget,
+ GtkDirectionType direction);
+
+static gpointer parent_class;
+static guint signals[LAST_SIGNAL] = { 0 };
+
+GType
+wnck_pager_get_type (void)
+{
+ static GType object_type = 0;
+
+ g_type_init ();
+
+ if (!object_type)
+ {
+ static const GTypeInfo object_info =
+ {
+ sizeof (WnckPagerClass),
+ (GBaseInitFunc) NULL,
+ (GBaseFinalizeFunc) NULL,
+ (GClassInitFunc) wnck_pager_class_init,
+ NULL, /* class_finalize */
+ NULL, /* class_data */
+ sizeof (WnckPager),
+ 0, /* n_preallocs */
+ (GInstanceInitFunc) wnck_pager_init,
+ };
+
+ object_type = g_type_register_static (GTK_TYPE_WIDGET,
+ "WnckPager",
+ &object_info, 0);
+ }
+
+ return object_type;
+}
+
+static void
+wnck_pager_init (WnckPager *pager)
+{
+ pager->priv = g_new0 (WnckPagerPrivate, 1);
+
+ pager->priv->n_rows = 1;
+ pager->priv->orientation = GTK_ORIENTATION_HORIZONTAL;
+}
+
+static void
+wnck_pager_class_init (WnckPagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+ parent_class = g_type_class_peek_parent (klass);
+
+ object_class->finalize = wnck_pager_finalize;
+
+ widget_class->realize = wnck_pager_realize;
+ widget_class->unrealize = wnck_pager_unrealize;
+ widget_class->size_request = wnck_pager_size_request;
+ widget_class->size_allocate = wnck_pager_size_allocate;
+ widget_class->expose_event = wnck_pager_expose_event;
+ widget_class->button_press_event = wnck_pager_button_press;
+ widget_class->focus = wnck_pager_focus;
+}
+
+static void
+wnck_pager_finalize (GObject *object)
+{
+ WnckPager *pager;
+
+ pager = WNCK_PAGER (object);
+
+ g_free (pager->priv);
+
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static void
+wnck_pager_realize (GtkWidget *widget)
+{
+
+ GdkWindowAttr attributes;
+ gint attributes_mask;
+ WnckPager *pager;
+
+ pager = WNCK_PAGER (widget);
+
+ GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.x = widget->allocation.x;
+ attributes.y = widget->allocation.y;
+ attributes.width = widget->allocation.width;
+ attributes.height = widget->allocation.height;
+ attributes.wclass = GDK_INPUT_OUTPUT;
+ attributes.visual = gtk_widget_get_visual (widget);
+ attributes.colormap = gtk_widget_get_colormap (widget);
+ attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK;
+
+ attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
+
+ widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
+ gdk_window_set_user_data (widget->window, widget);
+
+ widget->style = gtk_style_attach (widget->style, widget->window);
+ gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
+}
+
+static void
+wnck_pager_unrealize (GtkWidget *widget)
+{
+
+ GTK_WIDGET_CLASS (parent_class)->unrealize (widget);
+}
+
+static void
+wnck_pager_size_request (GtkWidget *widget,
+ GtkRequisition *requisition)
+{
+ WnckPager *pager;
+ int n_spaces;
+ int spaces_per_row;
+
+ pager = WNCK_PAGER (widget);
+
+ n_spaces = wnck_screen_get_workspace_count (pager->priv->screen);
+
+ g_assert (pager->priv->n_rows > 0);
+ spaces_per_row = n_spaces / pager->priv->n_rows;
+
+ if (pager->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ requisition->width = MIN_WORKSPACE_SIZE * pager->priv->n_rows;
+ requisition->height = MIN_WORKSPACE_SIZE * spaces_per_row;
+ }
+ else
+ {
+ requisition->width = MIN_WORKSPACE_SIZE * spaces_per_row;
+ requisition->height = MIN_WORKSPACE_SIZE * pager->priv->n_rows;
+ }
+
+ g_print ("Requesting %d x %d\n", requisition->width, requisition->height);
+}
+
+static void
+wnck_pager_size_allocate (GtkWidget *widget,
+ GtkAllocation *allocation)
+{
+ WnckPager *pager;
+
+ pager = WNCK_PAGER (widget);
+
+ GTK_WIDGET_CLASS (parent_class)->size_allocate (widget, allocation);
+}
+
+static void
+get_workspace_rect (WnckPager *pager,
+ int space,
+ GdkRectangle *rect)
+{
+ int n_spaces;
+ int spaces_per_row;
+ GtkWidget *widget;
+
+ widget = GTK_WIDGET (pager);
+
+ n_spaces = wnck_screen_get_workspace_count (pager->priv->screen);
+
+ g_assert (pager->priv->n_rows > 0);
+ spaces_per_row = n_spaces / pager->priv->n_rows;
+
+ if (pager->priv->orientation == GTK_ORIENTATION_VERTICAL)
+ {
+ rect->width = widget->allocation.width / pager->priv->n_rows;
+ rect->height = widget->allocation.height / spaces_per_row;
+ rect->x = rect->width * (space % pager->priv->n_rows);
+ rect->y = rect->height * (space % spaces_per_row);
+ }
+ else
+ {
+ rect->width = widget->allocation.width / spaces_per_row;
+ rect->height = widget->allocation.height / pager->priv->n_rows;
+ rect->x = rect->width * (space % spaces_per_row);
+ rect->y = rect->height * (space % pager->priv->n_rows);
+ }
+}
+
+
+static gboolean
+wnck_pager_expose_event (GtkWidget *widget,
+ GdkEventExpose *event)
+{
+ WnckPager *pager;
+ int i;
+ int n_spaces;
+ WnckWorkspace *active_space;
+
+ pager = WNCK_PAGER (widget);
+
+ n_spaces = wnck_screen_get_workspace_count (pager->priv->screen);
+ active_space = wnck_screen_get_active_workspace (pager->priv->screen);
+
+ i = 0;
+ while (i < n_spaces)
+ {
+ GdkRectangle rect;
+
+ get_workspace_rect (pager, i, &rect);
+
+ gdk_draw_rectangle (widget->window,
+ widget->style->black_gc,
+ FALSE,
+ rect.x, rect.y, rect.width, rect.height);
+
+ if (active_space &&
+ i == wnck_workspace_get_number (active_space))
+ gdk_draw_rectangle (widget->window,
+ widget->style->white_gc,
+ TRUE,
+ rect.x + 1, rect.y + 1, rect.width - 2, rect.height - 2);
+
+ ++i;
+ }
+
+ return FALSE;
+}
+
+#define POINT_IN_RECT(xcoord, ycoord, rect) \
+ ((xcoord) >= (rect).x && \
+ (xcoord) < ((rect).x + (rect).width) && \
+ (ycoord) >= (rect).y && \
+ (ycoord) < ((rect).y + (rect).height))
+
+static gboolean
+wnck_pager_button_press (GtkWidget *widget,
+ GdkEventButton *event)
+{
+ WnckPager *pager;
+ int i;
+ int n_spaces;
+
+ pager = WNCK_PAGER (widget);
+
+ n_spaces = wnck_screen_get_workspace_count (pager->priv->screen);
+
+ i = 0;
+ while (i < n_spaces)
+ {
+ GdkRectangle rect;
+
+ get_workspace_rect (pager, i, &rect);
+
+
+ if (POINT_IN_RECT (event->x, event->y, rect))
+ {
+ WnckWorkspace *space = wnck_workspace_get (i);
+
+ if (space)
+ wnck_workspace_activate (space);
+
+ break;
+ }
+
+ ++i;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+wnck_pager_focus (GtkWidget *widget,
+ GtkDirectionType direction)
+{
+ WnckPager *pager;
+
+ pager = WNCK_PAGER (widget);
+
+ return GTK_WIDGET_CLASS (parent_class)->focus (widget, direction);
+}
+
+GtkWidget*
+wnck_pager_new (WnckScreen *screen)
+{
+ WnckPager *pager;
+
+ pager = g_object_new (WNCK_TYPE_PAGER, NULL);
+
+ pager->priv->screen = screen;
+
+ return GTK_WIDGET (pager);
+}
+
+void
+wnck_pager_set_orientation (WnckPager *pager,
+ GtkOrientation orientation)
+{
+ g_return_if_fail (WNCK_IS_PAGER (pager));
+
+ if (pager->priv->orientation == orientation)
+ return;
+
+ pager->priv->orientation = orientation;
+ gtk_widget_queue_resize (GTK_WIDGET (pager));
+}
diff --git a/libwnck/pager.h b/libwnck/pager.h
new file mode 100644
index 0000000..098fd98
--- /dev/null
+++ b/libwnck/pager.h
@@ -0,0 +1,64 @@
+/* pager object */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *
+ * 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.
+ */
+
+#ifndef WNCK_PAGER_H
+#define WNCK_PAGER_H
+
+#include <gtk/gtk.h>
+#include <libwnck/screen.h>
+
+G_BEGIN_DECLS
+
+#define WNCK_TYPE_PAGER (wnck_pager_get_type ())
+#define WNCK_PAGER(object) (G_TYPE_CHECK_INSTANCE_CAST ((object), WNCK_TYPE_PAGER, WnckPager))
+#define WNCK_PAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), WNCK_TYPE_PAGER, WnckPagerClass))
+#define WNCK_IS_PAGER(object) (G_TYPE_CHECK_INSTANCE_TYPE ((object), WNCK_TYPE_PAGER))
+#define WNCK_IS_PAGER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), WNCK_TYPE_PAGER))
+#define WNCK_PAGER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), WNCK_TYPE_PAGER, WnckPagerClass))
+
+typedef struct _WnckPager WnckPager;
+typedef struct _WnckPagerClass WnckPagerClass;
+typedef struct _WnckPagerPrivate WnckPagerPrivate;
+
+struct _WnckPager
+{
+ GtkContainer parent_instance;
+
+ WnckPagerPrivate *priv;
+};
+
+struct _WnckPagerClass
+{
+ GtkContainerClass parent_class;
+};
+
+GType wnck_pager_get_type (void) G_GNUC_CONST;
+
+GtkWidget* wnck_pager_new (WnckScreen *screen);
+
+void wnck_pager_set_orientation (WnckPager *pager,
+ GtkOrientation orientation);
+
+G_END_DECLS
+
+#endif /* WNCK_PAGER_H */
+
+
diff --git a/libwnck/private.h b/libwnck/private.h
index cf18caa..bae640f 100644
--- a/libwnck/private.h
+++ b/libwnck/private.h
@@ -35,7 +35,8 @@ void _wnck_window_process_property_notify (WnckWindow *window,
void _wnck_screen_process_property_notify (WnckScreen *screen,
XEvent *xevent);
-
+void _wnck_window_process_configure_notify (WnckWindow *window,
+ XEvent *xevent);
WnckWindow* _wnck_window_create (Window xwindow,
WnckScreen *screen);
void _wnck_window_destroy (WnckWindow *window);
diff --git a/libwnck/screen.c b/libwnck/screen.c
index d5835f1..a0eb2b2 100644
--- a/libwnck/screen.c
+++ b/libwnck/screen.c
@@ -84,6 +84,7 @@ static void update_active_window (WnckScreen *screen);
static void queue_update (WnckScreen *screen);
static void unqueue_update (WnckScreen *screen);
+static void do_update_now (WnckScreen *screen);
static void emit_active_window_changed (WnckScreen *screen);
static void emit_active_workspace_changed (WnckScreen *screen);
@@ -413,6 +414,40 @@ wnck_screen_get_windows_stacked (WnckScreen *screen)
return screen->priv->stacked_windows;
}
+/**
+ * wnck_screen_force_update:
+ * @screen: a #WnckScreen
+ *
+ * Synchronously and immediately update the window list. This is
+ * usually a bad idea for both performance and correctness reasons (to
+ * get things right, you need to write model-view code that tracks
+ * changes, not get a static list of open windows).
+ *
+ **/
+void
+wnck_screen_force_update (WnckScreen *screen)
+{
+ g_return_if_fail (WNCK_IS_SCREEN (screen));
+
+ do_update_now (screen);
+}
+
+/**
+ * wnck_screen_get_workspace_count:
+ * @screen: a #WnckScreen
+ *
+ * Gets the number of workspaces.
+ *
+ * Return value: number of workspaces
+ **/
+int
+wnck_screen_get_workspace_count (WnckScreen *screen)
+{
+ g_return_val_if_fail (WNCK_IS_SCREEN (screen), 0);
+
+ return g_list_length (screen->priv->workspaces);
+}
+
void
_wnck_screen_process_property_notify (WnckScreen *screen,
XEvent *xevent)
@@ -961,14 +996,14 @@ update_active_window (WnckScreen *screen)
emit_active_window_changed (screen);
}
-static gboolean
-update_idle (gpointer data)
+static void
+do_update_now (WnckScreen *screen)
{
- WnckScreen *screen;
-
- screen = data;
-
- screen->priv->update_handler = 0;
+ if (screen->priv->update_handler)
+ {
+ g_source_remove (screen->priv->update_handler);
+ screen->priv->update_handler = 0;
+ }
/* First get our big-picture state in order */
update_workspace_list (screen);
@@ -977,6 +1012,18 @@ update_idle (gpointer data)
/* Then note any smaller-scale changes */
update_active_workspace (screen);
update_active_window (screen);
+}
+
+static gboolean
+update_idle (gpointer data)
+{
+ WnckScreen *screen;
+
+ screen = data;
+
+ screen->priv->update_handler = 0;
+
+ do_update_now (screen);
return FALSE;
}
diff --git a/libwnck/screen.h b/libwnck/screen.h
index 9c622bb..7bde5f8 100644
--- a/libwnck/screen.h
+++ b/libwnck/screen.h
@@ -93,6 +93,10 @@ WnckWindow* wnck_screen_get_active_window (WnckScreen *screen);
GList* wnck_screen_get_windows (WnckScreen *screen);
GList* wnck_screen_get_windows_stacked (WnckScreen *screen);
+void wnck_screen_force_update (WnckScreen *screen);
+
+int wnck_screen_get_workspace_count (WnckScreen *screen);
+
G_END_DECLS
#endif /* WNCK_SCREEN_H */
diff --git a/libwnck/test-pager.c b/libwnck/test-pager.c
new file mode 100644
index 0000000..9f5af7f
--- /dev/null
+++ b/libwnck/test-pager.c
@@ -0,0 +1,61 @@
+
+#include <libwnck/libwnck.h>
+#include <gtk/gtk.h>
+
+static void
+create_pager_window (WnckScreen *screen,
+ GtkOrientation orientation)
+{
+ GtkWidget *win;
+ GtkWidget *pager;
+ GtkWidget *frame;
+
+ win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_stick (GTK_WINDOW (win));
+ wnck_gtk_window_set_dock_type (GTK_WINDOW (win));
+
+ gtk_window_set_title (GTK_WINDOW (win), "Pager");
+
+ /* very very random */
+ gtk_window_move (GTK_WINDOW (win),
+ gdk_screen_width () / 2,
+ gdk_screen_height () - 20);
+
+ /* quit on window close */
+ g_signal_connect (G_OBJECT (win), "destroy",
+ G_CALLBACK (gtk_main_quit),
+ NULL);
+
+ frame = gtk_frame_new (NULL);
+ gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_IN);
+ gtk_container_add (GTK_CONTAINER (win), frame);
+
+ pager = wnck_pager_new (screen);
+
+ wnck_pager_set_orientation (WNCK_PAGER (pager), orientation);
+
+ gtk_container_add (GTK_CONTAINER (frame), pager);
+
+ gtk_widget_show_all (win);
+}
+
+int
+main (int argc, char **argv)
+{
+ WnckScreen *screen;
+
+ gtk_init (&argc, &argv);
+
+ screen = wnck_screen_get (0);
+
+ /* because the pager doesn't respond to signals at the moment */
+ wnck_screen_force_update (screen);
+
+ create_pager_window (screen, GTK_ORIENTATION_HORIZONTAL);
+ /* create_pager_window (screen, GTK_ORIENTATION_VERTICAL); */
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/libwnck/test-wnck.c b/libwnck/test-wnck.c
index 5a3b90a..f476157 100644
--- a/libwnck/test-wnck.c
+++ b/libwnck/test-wnck.c
@@ -38,6 +38,8 @@ static void window_workspace_changed_callback (WnckWindow *window,
gpointer data);
static void window_icon_changed_callback (WnckWindow *window,
gpointer data);
+static void window_geometry_changed_callback (WnckWindow *window,
+ gpointer data);
static GtkTreeModel* create_tree_model (void);
static GtkWidget* create_tree_view (void);
@@ -169,7 +171,10 @@ window_opened_callback (WnckScreen *screen,
g_signal_connect (G_OBJECT (window), "icon_changed",
G_CALLBACK (window_icon_changed_callback),
NULL);
-
+ g_signal_connect (G_OBJECT (window), "geometry_changed",
+ G_CALLBACK (window_geometry_changed_callback),
+ NULL);
+
queue_refill_model ();
}
@@ -303,6 +308,18 @@ window_icon_changed_callback (WnckWindow *window,
update_window (global_tree_model, window);
}
+static void
+window_geometry_changed_callback (WnckWindow *window,
+ gpointer data)
+{
+ int x, y, width, height;
+
+ wnck_window_get_geometry (window, &x, &y, &width, &height);
+
+ g_print ("Geometry changed on window '%s': %d,%d %d x %d\n",
+ wnck_window_get_name (window), x, y, width, height);
+}
+
static GtkTreeModel*
create_tree_model (void)
{
diff --git a/libwnck/util.c b/libwnck/util.c
new file mode 100644
index 0000000..837c93e
--- /dev/null
+++ b/libwnck/util.c
@@ -0,0 +1,42 @@
+/* util header */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *
+ * 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.
+ */
+
+#include "util.h"
+#include "xutils.h"
+#include <gdk/gdkx.h>
+
+static void
+set_dock_realize_handler (GtkWidget *widget, gpointer data)
+{
+ _wnck_set_dock_type_hint (GDK_WINDOW_XWINDOW (widget->window));
+}
+
+void
+wnck_gtk_window_set_dock_type (GtkWindow *window)
+{
+ /* FIXME don't set it 10 times if this function is called 10 times */
+ g_signal_connect (G_OBJECT (window),
+ "realize",
+ G_CALLBACK (set_dock_realize_handler),
+ NULL);
+}
+
+
diff --git a/libwnck/util.h b/libwnck/util.h
new file mode 100644
index 0000000..a9863d9
--- /dev/null
+++ b/libwnck/util.h
@@ -0,0 +1,31 @@
+/* util header */
+
+/*
+ * Copyright (C) 2001 Havoc Pennington
+ *
+ * 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.
+ */
+
+#ifndef WNCK_UTIL_H
+#define WNCK_UTIL_H
+
+#include <gtk/gtk.h>
+
+void wnck_gtk_window_set_dock_type (GtkWindow *window);
+
+#endif /* WNCK_UTIL_H */
+
+
diff --git a/libwnck/window.c b/libwnck/window.c
index d7ec3da..f887b81 100644
--- a/libwnck/window.c
+++ b/libwnck/window.c
@@ -68,6 +68,11 @@ struct _WnckWindowPrivate
GdkPixbuf *mini_icon;
WnckWindowActions actions;
+
+ int x;
+ int y;
+ int width;
+ int height;
/* window has no icon, don't bother querying the
* properties again
@@ -112,6 +117,7 @@ enum {
WORKSPACE_CHANGED,
ICON_CHANGED,
ACTIONS_CHANGED,
+ GEOMETRY_CHANGED,
LAST_SIGNAL
};
@@ -128,6 +134,7 @@ static void emit_icon_changed (WnckWindow *window);
static void emit_actions_changed (WnckWindow *window,
WnckWindowActions changed_mask,
WnckWindowActions new_actions);
+static void emit_geometry_changed (WnckWindow *window);
static void update_name (WnckWindow *window);
static void update_state (WnckWindow *window);
@@ -245,7 +252,15 @@ wnck_window_class_init (WnckWindowClass *klass)
G_TYPE_NONE, 2,
WNCK_TYPE_WINDOW_ACTIONS,
WNCK_TYPE_WINDOW_ACTIONS);
-
+
+ signals[GEOMETRY_CHANGED] =
+ g_signal_new ("geometry_changed",
+ G_OBJECT_CLASS_TYPE (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (WnckWindowClass, geometry_changed),
+ NULL, NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
}
static void
@@ -327,11 +342,11 @@ _wnck_window_create (Window xwindow,
/* Hash now owns one ref, caller gets none */
/* Note that xwindow may correspond to a WnckApplication's xwindow,
- * right now it doesn't matter since we use PropertyChangeMask both
- * places
+ * that's why we select the union of the mask we want for Application
+ * and the one we want for window
*/
_wnck_select_input (window->priv->xwindow,
- PropertyChangeMask);
+ WNCK_APP_WINDOW_EVENT_MASK);
window->priv->group_leader =
_wnck_get_group_leader (window->priv->xwindow);
@@ -342,6 +357,12 @@ _wnck_window_create (Window xwindow,
window->priv->pid =
_wnck_get_pid (window->priv->xwindow);
+ _wnck_get_window_geometry (xwindow,
+ &window->priv->x,
+ &window->priv->y,
+ &window->priv->width,
+ &window->priv->height);
+
window->priv->need_update_name = TRUE;
window->priv->need_update_state = TRUE;
window->priv->need_update_icon_name = TRUE;
@@ -999,6 +1020,39 @@ wnck_window_get_state (WnckWindow *window)
return COMPRESS_STATE (window);
}
+/**
+ * wnck_window_get_geometry:
+ * @window: a #WnckWindow
+ * @xp: return location for X coordinate of window
+ * @yp: return location for Y coordinate of window
+ * @widthp: return location for width of window
+ * @heightp: return location for height of window
+ *
+ * Gets the size and position of the window, as last received
+ * in a configure notify (i.e. this call does not round-trip
+ * to the server, just gets the last size we were notified of).
+ * The X and Y coordinates are relative to the root window.
+ *
+ **/
+void
+wnck_window_get_geometry (WnckWindow *window,
+ int *xp,
+ int *yp,
+ int *widthp,
+ int *heightp)
+{
+ g_return_if_fail (WNCK_IS_WINDOW (window));
+
+ if (xp)
+ *xp = window->priv->x;
+ if (yp)
+ *yp = window->priv->y;
+ if (widthp)
+ *widthp = window->priv->width;
+ if (heightp)
+ *heightp = window->priv->height;
+}
+
void
_wnck_window_set_application (WnckWindow *window,
WnckApplication *app)
@@ -1074,6 +1128,28 @@ _wnck_window_process_property_notify (WnckWindow *window,
}
}
+void
+_wnck_window_process_configure_notify (WnckWindow *window,
+ XEvent *xevent)
+{
+ if (xevent->xconfigure.send_event)
+ {
+ window->priv->x = xevent->xconfigure.x;
+ window->priv->y = xevent->xconfigure.y;
+ }
+ else
+ {
+ _wnck_get_window_position (window->priv->xwindow,
+ &window->priv->x,
+ &window->priv->y);
+ }
+
+ window->priv->width = xevent->xconfigure.width;
+ window->priv->height = xevent->xconfigure.height;
+
+ emit_geometry_changed (window);
+}
+
static void
update_minimized (WnckWindow *window)
{
@@ -1398,3 +1474,11 @@ emit_actions_changed (WnckWindow *window,
signals[ACTIONS_CHANGED],
0, changed_mask, new_actions);
}
+
+static void
+emit_geometry_changed (WnckWindow *window)
+{
+ g_signal_emit (G_OBJECT (window),
+ signals[GEOMETRY_CHANGED],
+ 0);
+}
diff --git a/libwnck/window.h b/libwnck/window.h
index d9f1001..7f7b126 100644
--- a/libwnck/window.h
+++ b/libwnck/window.h
@@ -104,6 +104,9 @@ struct _WnckWindowClass
void (* actions_changed) (WnckWindow *window,
WnckWindowActions changed_mask,
WnckWindowActions new_actions);
+
+ /* Changed size/position */
+ void (* geometry_changed) (WnckWindow *window);
};
GType wnck_window_get_type (void) G_GNUC_CONST;
@@ -173,6 +176,12 @@ void wnck_window_set_mini_icon_size (WnckWindow *window,
WnckWindowActions wnck_window_get_actions (WnckWindow *window);
WnckWindowState wnck_window_get_state (WnckWindow *window);
+void wnck_window_get_geometry (WnckWindow *window,
+ int *xp,
+ int *yp,
+ int *widthp,
+ int *heightp);
+
G_END_DECLS
#endif /* WNCK_WINDOW_H */
diff --git a/libwnck/workspace.c b/libwnck/workspace.c
index 7b3c490..5fb21ca 100644
--- a/libwnck/workspace.c
+++ b/libwnck/workspace.c
@@ -20,6 +20,7 @@
*/
#include "workspace.h"
+#include "xutils.h"
static GHashTable* workspace_hash = NULL;
@@ -125,6 +126,14 @@ wnck_workspace_get (int number)
return g_hash_table_lookup (workspace_hash, &number);
}
+/**
+ * wnck_workspace_get_number:
+ * @space: a #WnckWorkspace
+ *
+ *
+ *
+ * Return value: get the index of the workspace
+ **/
int
wnck_workspace_get_number (WnckWorkspace *space)
{
@@ -133,6 +142,21 @@ wnck_workspace_get_number (WnckWorkspace *space)
return space->priv->number;
}
+/**
+ * wnck_workspace_activate:
+ * @space: a #WnckWorkspace
+ *
+ * Ask window manager to make @space the active workspace.
+ *
+ **/
+void
+wnck_workspace_activate (WnckWorkspace *space)
+{
+ g_return_if_fail (WNCK_IS_WORKSPACE (space));
+
+ _wnck_activate_workspace (space->priv->number);
+}
+
WnckWorkspace*
_wnck_workspace_create (int number)
{
diff --git a/libwnck/workspace.h b/libwnck/workspace.h
index 49c97d3..1571824 100644
--- a/libwnck/workspace.h
+++ b/libwnck/workspace.h
@@ -56,6 +56,8 @@ WnckWorkspace* wnck_workspace_get (int number);
int wnck_workspace_get_number (WnckWorkspace *space);
+void wnck_workspace_activate (WnckWorkspace *space);
+
G_END_DECLS
#endif /* WNCK_WORKSPACE_H */
diff --git a/libwnck/xutils.c b/libwnck/xutils.c
index 6077a6c..163eaa7 100644
--- a/libwnck/xutils.c
+++ b/libwnck/xutils.c
@@ -19,6 +19,7 @@
* Boston, MA 02111-1307, USA.
*/
+#include <config.h>
#include "xutils.h"
#include <string.h>
#include "screen.h"
@@ -144,7 +145,7 @@ text_property_to_utf8 (const XTextProperty *prop)
list = NULL;
- count = gdk_text_property_to_utf8_list (prop->encoding,
+ count = gdk_text_property_to_utf8_list (gdk_x11_xatom_to_atom (prop->encoding),
prop->format,
prop->value,
prop->nitems,
@@ -418,9 +419,9 @@ static GHashTable *reverse_atom_hash = NULL;
Atom
_wnck_atom_get (const char *atom_name)
{
- GdkAtom retval;
+ Atom retval;
- g_return_val_if_fail (atom_name != NULL, GDK_NONE);
+ g_return_val_if_fail (atom_name != NULL, None);
if (!atom_hash)
{
@@ -487,6 +488,17 @@ filter_func (GdkXEvent *gdkxevent,
}
}
break;
+
+ case ConfigureNotify:
+ {
+ WnckWindow *window;
+
+ window = wnck_window_get (xevent->xany.window);
+
+ if (window)
+ _wnck_window_process_configure_notify (window, xevent);
+ }
+ break;
}
return GDK_FILTER_CONTINUE;
@@ -651,6 +663,29 @@ _wnck_activate (Window xwindow)
&xev);
}
+void
+_wnck_activate_workspace (int new_active_space)
+{
+ XEvent xev;
+
+ xev.xclient.type = ClientMessage;
+ xev.xclient.serial = 0;
+ xev.xclient.send_event = True;
+ xev.xclient.display = gdk_display;
+ xev.xclient.window = gdk_x11_get_default_root_xwindow ();
+ xev.xclient.message_type = _wnck_atom_get ("_NET_CURRENT_DESKTOP");
+ xev.xclient.format = 32;
+ xev.xclient.data.l[0] = new_active_space;
+ xev.xclient.data.l[1] = 0;
+ xev.xclient.data.l[2] = 0;
+
+ XSendEvent (gdk_display,
+ gdk_x11_get_default_root_xwindow (),
+ False,
+ SubstructureRedirectMask | SubstructureNotifyMask,
+ &xev);
+}
+
Window
_wnck_get_group_leader (Window xwindow)
{
@@ -1315,6 +1350,10 @@ _wnck_read_icons (Window xwindow,
/* No further ideas... */
}
+#ifdef HAVE_GDK_PIXBUF_NEW_FROM_STREAM
+#define gdk_pixbuf_new_from_inline gdk_pixbuf_new_from_stream
+#endif
+
static GdkPixbuf*
default_icon_at_size (int width,
int height)
@@ -1322,7 +1361,7 @@ default_icon_at_size (int width,
GdkPixbuf *base;
- base = gdk_pixbuf_new_from_stream (-1, default_icon_data,
+ base = gdk_pixbuf_new_from_inline (-1, default_icon_data,
FALSE,
NULL);
@@ -1371,3 +1410,75 @@ _wnck_get_fallback_icons (GdkPixbuf **iconp,
}
+void
+_wnck_get_window_geometry (Window xwindow,
+ int *xp,
+ int *yp,
+ int *widthp,
+ int *heightp)
+{
+ int x, y, width, height, bw, depth;
+ Window root_window;
+
+ width = 1;
+ height = 1;
+
+ _wnck_error_trap_push ();
+
+ XGetGeometry (gdk_display,
+ xwindow,
+ &root_window,
+ &x, &y, &width, &height, &bw, &depth);
+
+ _wnck_error_trap_pop ();
+
+ _wnck_get_window_position (xwindow, xp, yp);
+
+ if (widthp)
+ *widthp = width;
+ if (heightp)
+ *heightp = height;
+}
+
+void
+_wnck_get_window_position (Window xwindow,
+ int *xp,
+ int *yp)
+{
+ int x, y;
+ Window child;
+
+ x = 0;
+ y = 0;
+
+ _wnck_error_trap_push ();
+ XTranslateCoordinates (gdk_display,
+ xwindow,
+ gdk_x11_get_default_root_xwindow (),
+ 0, 0,
+ &x, &y, &child);
+ _wnck_error_trap_pop ();
+
+ if (xp)
+ *xp = x;
+ if (yp)
+ *yp = y;
+}
+
+void
+_wnck_set_dock_type_hint (Window xwindow)
+{
+ Atom atom;
+
+ atom = _wnck_atom_get ("_NET_WM_WINDOW_TYPE_DOCK");
+
+ _wnck_error_trap_push ();
+
+ XChangeProperty (gdk_display,
+ xwindow,
+ _wnck_atom_get ("_NET_WM_WINDOW_TYPE"),
+ XA_ATOM, 32, PropModeReplace,
+ (guchar *)&atom, 1);
+
+ _wnck_error_trap_pop ();
+}
diff --git a/libwnck/xutils.h b/libwnck/xutils.h
index bb95680..c5566e4 100644
--- a/libwnck/xutils.h
+++ b/libwnck/xutils.h
@@ -30,6 +30,8 @@
G_BEGIN_DECLS
+#define WNCK_APP_WINDOW_EVENT_MASK (PropertyChangeMask | StructureNotifyMask)
+
gboolean _wnck_get_cardinal (Window xwindow,
Atom atom,
int *val);
@@ -79,6 +81,7 @@ void _wnck_change_state (Window xwindow,
void _wnck_change_workspace (Window xwindow,
int new_space);
void _wnck_activate (Window xwindow);
+void _wnck_activate_workspace (int new_active_space);
Window _wnck_get_group_leader (Window xwindow);
char* _wnck_get_session_id (Window xwindow);
@@ -103,6 +106,18 @@ void _wnck_get_fallback_icons (GdkPixbuf **iconp,
int ideal_mini_height);
+void _wnck_get_window_geometry (Window xwindow,
+ int *xp,
+ int *yp,
+ int *widthp,
+ int *heightp);
+
+void _wnck_get_window_position (Window xwindow,
+ int *xp,
+ int *yp);
+
+void _wnck_set_dock_type_hint (Window xwindow);
+
G_END_DECLS
#endif /* WNCK_XUTILS_H */