diff --git a/src/frame.c b/src/frame.c index 789509ca4..fd23b6708 100644 --- a/src/frame.c +++ b/src/frame.c @@ -47,6 +47,9 @@ struct _MetaFrameActionGrab static void clear_tip (MetaFrame *frame); +static guint draw_handler = 0; +static GSList *draw_pending = NULL; + static void meta_frame_init_info (MetaFrame *frame, MetaFrameInfo *info) @@ -93,26 +96,6 @@ meta_frame_init_info (MetaFrame *frame, info->current_control_state = META_STATE_PRELIGHT; } -static void -pango_hack_start (MetaDisplay *display) -{ - if (display->server_grab_count > 0) - { - meta_verbose ("Pango workaround, ungrabbing server\n"); - XUngrabServer (display->xdisplay); - } -} - -static void -pango_hack_end (MetaDisplay *display) -{ - if (display->server_grab_count > 0) - { - meta_verbose ("Pango workaround, regrabbing server\n"); - XGrabServer (display->xdisplay); - } -} - void meta_frame_calc_geometry (MetaFrame *frame, int child_width, int child_height, @@ -140,7 +123,10 @@ meta_frame_calc_geometry (MetaFrame *frame, info.height = child_height; if (!frame->theme_acquired) - frame->theme_data = window->screen->engine->acquire_frame (&info); + { + frame->theme_data = window->screen->engine->acquire_frame (&info); + frame->theme_acquired = TRUE; + } geom.left_width = 0; geom.right_width = 0; @@ -152,10 +138,8 @@ meta_frame_calc_geometry (MetaFrame *frame, geom.shape_mask = None; - pango_hack_start (frame->window->display); window->screen->engine->fill_frame_geometry (&info, &geom, frame->theme_data); - pango_hack_end (frame->window->display); *geomp = geom; } @@ -191,7 +175,7 @@ set_background_color (MetaFrame *frame) { XSetWindowAttributes attrs; - attrs.background_pixel = None; + attrs.background_pixel = frame->bg_pixel; XChangeWindowAttributes (frame->window->display->xdisplay, frame->xwindow, CWBackPixel, @@ -226,6 +210,9 @@ meta_window_ensure_frame (MetaWindow *window) frame->bg_pixel = 0; frame->mapped = FALSE; + + frame->edges_exposed = FALSE; + frame->title_exposed = FALSE; attrs.event_mask = EVENT_MASK; @@ -283,6 +270,11 @@ meta_window_destroy_frame (MetaWindow *window) frame = window->frame; + if (frame->title_exposed || frame->edges_exposed) + { + draw_pending = g_slist_remove (draw_pending, frame); + } + if (frame->tooltip_timeout) clear_tip (frame); @@ -403,12 +395,10 @@ meta_frame_draw_now (MetaFrame *frame, info.drawable = p; info.xoffset = - x; info.yoffset = - y; - pango_hack_start (frame->window->display); + frame->window->screen->engine->expose_frame (&info, 0, 0, width, height, frame->theme_data); - pango_hack_end (frame->window->display); - XCopyArea (frame->window->display->xdisplay, p, frame->xwindow, @@ -419,13 +409,51 @@ meta_frame_draw_now (MetaFrame *frame, XFreePixmap (frame->window->display->xdisplay, p); + + frame->title_exposed = FALSE; + frame->edges_exposed = FALSE; +} + +static gboolean +draw_idle (gpointer data) +{ + GSList *tmp; + + tmp = draw_pending; + while (tmp != NULL) + { + int yoffset; + MetaFrame *frame; + + frame = tmp->data; + + yoffset = 0; + if (!frame->title_exposed) + yoffset += frame->child_y; + + meta_frame_draw_now (frame, 0, yoffset, + frame->rect.width, + frame->rect.height - yoffset); + tmp = tmp->next; + } + g_slist_free (draw_pending); + draw_pending = NULL; + + draw_handler = 0; + return FALSE; } void meta_frame_queue_draw (MetaFrame *frame) { - /* FIXME, actually queue */ - meta_frame_draw_now (frame, 0, 0, -1, -1); + if (draw_handler == 0) + draw_handler = g_idle_add (draw_idle, NULL); + + if (!(frame->title_exposed || frame->edges_exposed)) + draw_pending = g_slist_prepend (draw_pending, frame); + + frame->title_exposed = TRUE; + frame->edges_exposed = TRUE; } static void @@ -938,11 +966,13 @@ meta_frame_event (MetaFrame *frame, case KeymapNotify: break; case Expose: - meta_frame_draw_now (frame, - event->xexpose.x, - event->xexpose.y, - event->xexpose.width, - event->xexpose.height); + { + gboolean title_was_exposed = frame->title_exposed; + meta_frame_queue_draw (frame); + if (!title_was_exposed && + event->xexpose.y > frame->child_y) + frame->title_exposed = FALSE; + } break; case GraphicsExpose: break; diff --git a/src/frame.h b/src/frame.h index 83cfda341..314d1c200 100644 --- a/src/frame.h +++ b/src/frame.h @@ -63,6 +63,10 @@ struct _MetaFrame guint theme_acquired : 1; guint mapped : 1; + + /* world's lamest expose compression */ + guint edges_exposed : 1; + guint title_exposed : 1; }; void meta_window_ensure_frame (MetaWindow *window); diff --git a/src/frames.c b/src/frames.c new file mode 100644 index 000000000..0904e09db --- /dev/null +++ b/src/frames.c @@ -0,0 +1,125 @@ +/* Metacity window frame manager widget */ + +/* + * Copyright (C) 2001 Havoc Pennington + * + * 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 "frames.h" + +static void meta_frames_class_init (MetaFramesClass *klass); +static void meta_frames_init (MetaFrames *frames); +static void meta_frames_destroy (GtkObject *object); +static void meta_frames_finalize (GObject *object); +static void meta_frames_style_set (GtkWidget *widget, + GtkStyle *prev_style); + +static GtkWidgetClass *parent_class = NULL; +static guint signals[LAST_SIGNAL]; + +GtkType +meta_frames_get_type (void) +{ + static GtkType frames_type = 0; + + if (!frames_type) + { + static const GtkTypeInfo frames_info = + { + "MetaFrames", + sizeof (MetaFrames), + sizeof (MetaFramesClass), + (GtkClassInitFunc) meta_frames_class_init, + (GtkObjectInitFunc) meta_frames_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + frames_type = gtk_type_unique (GTK_TYPE_WIDGET, &frames_info); + } + + return frames_type; +} + +static void +meta_frames_class_init (MetaFramesClass *class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + gobject_class = G_OBJECT_CLASS (class); + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class->finalize = meta_frames_finalize; + object_class->destroy = meta_frames_destroy; + + widget_class->style_set = meta_frames_style_set; + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("slider_width", + _("Slider Width"), + _("Width of scrollbar or scale thumb"), + 0, + G_MAXINT, + 14, + G_PARAM_READABLE)); + +} + +static void +meta_frames_init (MetaFrames *frames) +{ + GTK_WINDOW (frames)->type = GTK_WINDOW_POPUP; +} + +static void +meta_frames_destroy (GtkObject *object) +{ + + +} + +static void +meta_frames_finalize (GObject *object) +{ + + +} + +void +meta_frames_manage_window (MetaFrames *frames, + GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + gdk_window_set_user_data (window, frames); + + gdk_window_set_events (window, + GDK_EXPOSURE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_STRUCTURE_MASK); +} + + diff --git a/src/frames.h b/src/frames.h new file mode 100644 index 000000000..c9c258358 --- /dev/null +++ b/src/frames.h @@ -0,0 +1,60 @@ +/* Metacity window frame manager widget */ + +/* + * Copyright (C) 2001 Havoc Pennington + * + * 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 META_FRAMES_H +#define META_FRAMES_H + +#include + +/* This is one widget that manages all the window frames + * as subwindows. + */ + +#define META_TYPE_FRAMES (meta_frames_get_type ()) +#define META_FRAMES(obj) (META_CHECK_CAST ((obj), META_TYPE_FRAMES, MetaFrames)) +#define META_FRAMES_CLASS(klass) (META_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass)) +#define META_IS_FRAMES(obj) (META_CHECK_TYPE ((obj), META_TYPE_FRAMES)) +#define META_IS_FRAMES_CLASS(klass) (META_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES)) +#define META_FRAMES_GET_CLASS(obj) (META_CHECK_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass)) + +typedef struct _MetaFrames MetaFrames; +typedef struct _MetaFramesClass MetaFramesClass; + +struct _MetaFrames +{ + GtkWindow parent_instance; + +}; + +struct _MetaFramesClass +{ + GtkWindowClass parent_class; + +}; + +GType meta_frames_get_type (void) G_GNUC_CONST; + +MetaFrames *meta_frames_new (void); + +void meta_frames_manage_window (MetaFrames *frames, + GdkWindow *window); + +#endif diff --git a/src/main.c b/src/main.c index a71ac08ad..e111d6e9b 100644 --- a/src/main.c +++ b/src/main.c @@ -39,6 +39,7 @@ main (int argc, char **argv) { struct sigaction act; sigset_t empty_mask; + char *display_name; sigemptyset (&empty_mask); act.sa_handler = SIG_IGN; @@ -57,6 +58,16 @@ main (int argc, char **argv) g_type_init (0); /* grumble */ meta_errors_init (); + + if (g_getenv ("METACITY_DISPLAY")) + { + meta_verbose ("Using METACITY_DISPLAY %s\n", + g_getenv ("METACITY_DISPLAY")); + display_name = + g_strconcat ("DISPLAY=", g_getenv ("METACITY_DISPLAY"), NULL); + putenv (display_name); + /* DO NOT FREE display_name, putenv() sucks */ + } if (!meta_display_open (NULL)) meta_exit (META_EXIT_ERROR); diff --git a/src/run-metacity.sh b/src/run-metacity.sh index cef1d7192..611d94a7a 100755 --- a/src/run-metacity.sh +++ b/src/run-metacity.sh @@ -29,5 +29,5 @@ if test -z "$ONLY_WM"; then fi if test -z "$ONLY_SETUP"; then - METACITY_UISLAVE_DIR=./uislave DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity + METACITY_UISLAVE_DIR=./uislave METACITY_DISPLAY=:1 exec unst libtool --mode=execute $DEBUG ./metacity fi diff --git a/src/screen.c b/src/screen.c index 5374b0082..f6029c50a 100644 --- a/src/screen.c +++ b/src/screen.c @@ -194,6 +194,9 @@ meta_screen_new (MetaDisplay *display, screen); screen->stack = meta_stack_new (screen); + + /* hack pango to get its coverage window */ + meta_screen_get_pango_context (screen, NULL, PANGO_DIRECTION_LTR); meta_verbose ("Added screen %d ('%s') root 0x%lx\n", screen->number, screen->screen_name, screen->xroot); @@ -354,7 +357,26 @@ meta_screen_get_pango_context (MetaScreen *screen, * are honored. */ pango_context_set_base_dir (ctx, direction); - pango_context_set_font_description (ctx, desc); + + if (desc == NULL) + { + desc = pango_font_description_from_string ("Sans 12"); + pango_context_set_font_description (ctx, desc); + pango_font_description_free (desc); + } + else + { + pango_context_set_font_description (ctx, desc); + } + + { + /* Make Pango grab server now not later */ + PangoLayout *hack; + hack = pango_layout_new (ctx); + pango_layout_set_text (hack, "foo", -1); + pango_layout_get_extents (hack, NULL, NULL); + g_object_unref (G_OBJECT (hack)); + } screen->pango_context = ctx; } diff --git a/src/theme.c b/src/theme.c index c80c2a3fb..76d104b92 100644 --- a/src/theme.c +++ b/src/theme.c @@ -601,7 +601,8 @@ default_expose_frame (MetaFrameInfo *info, draw_current_control_bg (info, &fgeom); - if (fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0) + if (y < fgeom.top_height && + fgeom.title_rect.width > 0 && fgeom.title_rect.height > 0) { int layout_y; MetaRectangle clip; diff --git a/src/uislave/frames.c b/src/uislave/frames.c new file mode 100644 index 000000000..0904e09db --- /dev/null +++ b/src/uislave/frames.c @@ -0,0 +1,125 @@ +/* Metacity window frame manager widget */ + +/* + * Copyright (C) 2001 Havoc Pennington + * + * 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 "frames.h" + +static void meta_frames_class_init (MetaFramesClass *klass); +static void meta_frames_init (MetaFrames *frames); +static void meta_frames_destroy (GtkObject *object); +static void meta_frames_finalize (GObject *object); +static void meta_frames_style_set (GtkWidget *widget, + GtkStyle *prev_style); + +static GtkWidgetClass *parent_class = NULL; +static guint signals[LAST_SIGNAL]; + +GtkType +meta_frames_get_type (void) +{ + static GtkType frames_type = 0; + + if (!frames_type) + { + static const GtkTypeInfo frames_info = + { + "MetaFrames", + sizeof (MetaFrames), + sizeof (MetaFramesClass), + (GtkClassInitFunc) meta_frames_class_init, + (GtkObjectInitFunc) meta_frames_init, + /* reserved_1 */ NULL, + /* reserved_2 */ NULL, + (GtkClassInitFunc) NULL, + }; + + frames_type = gtk_type_unique (GTK_TYPE_WIDGET, &frames_info); + } + + return frames_type; +} + +static void +meta_frames_class_init (MetaFramesClass *class) +{ + GObjectClass *gobject_class; + GtkObjectClass *object_class; + GtkWidgetClass *widget_class; + + gobject_class = G_OBJECT_CLASS (class); + object_class = (GtkObjectClass*) class; + widget_class = (GtkWidgetClass*) class; + + parent_class = g_type_class_peek_parent (class); + + gobject_class->finalize = meta_frames_finalize; + object_class->destroy = meta_frames_destroy; + + widget_class->style_set = meta_frames_style_set; + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("slider_width", + _("Slider Width"), + _("Width of scrollbar or scale thumb"), + 0, + G_MAXINT, + 14, + G_PARAM_READABLE)); + +} + +static void +meta_frames_init (MetaFrames *frames) +{ + GTK_WINDOW (frames)->type = GTK_WINDOW_POPUP; +} + +static void +meta_frames_destroy (GtkObject *object) +{ + + +} + +static void +meta_frames_finalize (GObject *object) +{ + + +} + +void +meta_frames_manage_window (MetaFrames *frames, + GdkWindow *window) +{ + g_return_if_fail (GDK_IS_WINDOW (window)); + + gdk_window_set_user_data (window, frames); + + gdk_window_set_events (window, + GDK_EXPOSURE_MASK | + GDK_POINTER_MOTION_MASK | + GDK_POINTER_MOTION_HINT_MASK | + GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_STRUCTURE_MASK); +} + + diff --git a/src/uislave/frames.h b/src/uislave/frames.h new file mode 100644 index 000000000..c9c258358 --- /dev/null +++ b/src/uislave/frames.h @@ -0,0 +1,60 @@ +/* Metacity window frame manager widget */ + +/* + * Copyright (C) 2001 Havoc Pennington + * + * 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 META_FRAMES_H +#define META_FRAMES_H + +#include + +/* This is one widget that manages all the window frames + * as subwindows. + */ + +#define META_TYPE_FRAMES (meta_frames_get_type ()) +#define META_FRAMES(obj) (META_CHECK_CAST ((obj), META_TYPE_FRAMES, MetaFrames)) +#define META_FRAMES_CLASS(klass) (META_CHECK_CLASS_CAST ((klass), META_TYPE_FRAMES, MetaFramesClass)) +#define META_IS_FRAMES(obj) (META_CHECK_TYPE ((obj), META_TYPE_FRAMES)) +#define META_IS_FRAMES_CLASS(klass) (META_CHECK_CLASS_TYPE ((klass), META_TYPE_FRAMES)) +#define META_FRAMES_GET_CLASS(obj) (META_CHECK_GET_CLASS ((obj), META_TYPE_FRAMES, MetaFramesClass)) + +typedef struct _MetaFrames MetaFrames; +typedef struct _MetaFramesClass MetaFramesClass; + +struct _MetaFrames +{ + GtkWindow parent_instance; + +}; + +struct _MetaFramesClass +{ + GtkWindowClass parent_class; + +}; + +GType meta_frames_get_type (void) G_GNUC_CONST; + +MetaFrames *meta_frames_new (void); + +void meta_frames_manage_window (MetaFrames *frames, + GdkWindow *window); + +#endif diff --git a/src/window.c b/src/window.c index ab8dd92b0..b68b2a707 100644 --- a/src/window.c +++ b/src/window.c @@ -324,7 +324,11 @@ meta_window_free (MetaWindow *window) window->border_width); meta_error_trap_pop (window->display); - + + g_free (window->sm_client_id); + g_free (window->role); + g_free (window->res_class); + g_free (window->res_name); g_free (window->title); g_free (window->desc); g_free (window); diff --git a/src/window.h b/src/window.h index c5d0d919b..b4c5a12ad 100644 --- a/src/window.h +++ b/src/window.h @@ -127,7 +127,7 @@ struct _MetaWindow */ guint user_has_resized : 1; guint user_has_moved : 1; - + /* Number of UnmapNotify that are caused by us, if * we get UnmapNotify with none pending then the client * is withdrawing the window.