diff options
author | Havoc Pennington <hp@redhat.com> | 2001-10-24 23:14:18 +0000 |
---|---|---|
committer | Havoc Pennington <hp@src.gnome.org> | 2001-10-24 23:14:18 +0000 |
commit | 1b33f9f46721f82a42d99cd4cd2947e95b3f8f50 (patch) | |
tree | 5682d207372228c76ebe302ab878aeb896236556 | |
parent | bd2798a0d5ade9f73bba408ae2353348a2858a74 (diff) | |
download | libwnck-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-- | ChangeLog | 12 | ||||
-rw-r--r-- | configure.in | 6 | ||||
-rw-r--r-- | libwnck/Makefile.am | 9 | ||||
-rw-r--r-- | libwnck/application.c | 5 | ||||
-rw-r--r-- | libwnck/libwnck.h | 3 | ||||
-rw-r--r-- | libwnck/pager.c | 355 | ||||
-rw-r--r-- | libwnck/pager.h | 64 | ||||
-rw-r--r-- | libwnck/private.h | 3 | ||||
-rw-r--r-- | libwnck/screen.c | 61 | ||||
-rw-r--r-- | libwnck/screen.h | 4 | ||||
-rw-r--r-- | libwnck/test-pager.c | 61 | ||||
-rw-r--r-- | libwnck/test-wnck.c | 19 | ||||
-rw-r--r-- | libwnck/util.c | 42 | ||||
-rw-r--r-- | libwnck/util.h | 31 | ||||
-rw-r--r-- | libwnck/window.c | 92 | ||||
-rw-r--r-- | libwnck/window.h | 9 | ||||
-rw-r--r-- | libwnck/workspace.c | 24 | ||||
-rw-r--r-- | libwnck/workspace.h | 2 | ||||
-rw-r--r-- | libwnck/xutils.c | 119 | ||||
-rw-r--r-- | libwnck/xutils.h | 15 |
20 files changed, 916 insertions, 20 deletions
@@ -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 */ |