diff --git a/ChangeLog b/ChangeLog index 181e5d9be..8d34cd4dd 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +2003-08-16 Havoc Pennington + + Patch from Soeren Sandmann #108926 to improve opaque resize + + * src/frame.c (meta_window_ensure_frame): new function + + * src/ui.c (meta_ui_create_frame_window): new function to create + a frame with GDK, so that GDK's invalidation etc. work properly + 2003-08-16 Havoc Pennington * src/display.c (xcursor_for_op): fix cursor for diff --git a/src/frame.c b/src/frame.c index 4d22cacc5..ba6b21c7e 100644 --- a/src/frame.c +++ b/src/frame.c @@ -62,8 +62,6 @@ meta_window_ensure_frame (MetaWindow *window) frame->need_reapply_frame_shape = TRUE; frame->is_flashing = FALSE; - attrs.event_mask = EVENT_MASK; - meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n", window->desc, XVisualIDFromVisual (window->xvisual) == @@ -79,24 +77,19 @@ meta_window_ensure_frame (MetaWindow *window) * e.g. DRI games can't be children of a parent that has the same * visual as the client. */ - - frame->xwindow = XCreateWindow (window->display->xdisplay, - window->screen->xroot, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height, - 0, - window->screen->default_depth, - CopyFromParent, - window->screen->default_xvisual, - CWEventMask, - &attrs); - /* So our UI can find the window ID */ - XFlush (window->display->xdisplay); - + frame->xwindow = meta_ui_create_frame_window (window->screen->ui, + window->display->xdisplay, + frame->rect.x, + frame->rect.y, + frame->rect.width, + frame->rect.height, + frame->window->screen->number); + meta_verbose ("Frame for %s is 0x%lx\n", frame->window->desc, frame->xwindow); + attrs.event_mask = EVENT_MASK; + XChangeWindowAttributes (window->display->xdisplay, + frame->xwindow, CWEventMask, &attrs); meta_display_register_x_window (window->display, &frame->xwindow, window); @@ -133,8 +126,6 @@ meta_window_ensure_frame (MetaWindow *window) /* stick frame to the window */ window->frame = frame; - meta_ui_add_frame (window->screen->ui, frame->xwindow); - if (window->title) meta_ui_set_frame_title (window->screen->ui, window->frame->xwindow, @@ -165,7 +156,6 @@ meta_window_destroy_frame (MetaWindow *window) frame = window->frame; meta_bell_notify_frame_destroy (frame); - meta_ui_remove_frame (window->screen->ui, frame->xwindow); /* Unparent the client window; it may be destroyed, * thus the error trap. @@ -189,6 +179,8 @@ meta_window_destroy_frame (MetaWindow *window) window->frame->rect.y); meta_error_trap_pop (window->display, FALSE); + meta_ui_destroy_frame_window (window->screen->ui, frame->xwindow); + meta_display_unregister_x_window (window->display, frame->xwindow); @@ -197,9 +189,6 @@ meta_window_destroy_frame (MetaWindow *window) /* Move keybindings to window instead of frame */ meta_window_grab_keys (window); - /* should we push an error trap? */ - XDestroyWindow (window->display->xdisplay, frame->xwindow); - g_free (frame); /* Put our state back where it should be */ @@ -339,23 +328,12 @@ meta_frame_sync_to_window (MetaFrame *frame, */ update_shape (frame); - if (need_move && need_resize) - XMoveResizeWindow (frame->window->display->xdisplay, - frame->xwindow, - frame->rect.x, - frame->rect.y, - frame->rect.width, - frame->rect.height); - else if (need_move) - XMoveWindow (frame->window->display->xdisplay, - frame->xwindow, - frame->rect.x, - frame->rect.y); - else if (need_resize) - XResizeWindow (frame->window->display->xdisplay, - frame->xwindow, - frame->rect.width, - frame->rect.height); + meta_ui_move_resize_frame (frame->window->screen->ui, + frame->xwindow, + frame->rect.x, + frame->rect.y, + frame->rect.width, + frame->rect.height); if (need_resize) { @@ -379,8 +357,9 @@ meta_frame_queue_draw (MetaFrame *frame) frame->xwindow); } -void meta_frame_set_screen_cursor (MetaFrame *frame, - MetaCursor cursor) +void +meta_frame_set_screen_cursor (MetaFrame *frame, + MetaCursor cursor) { Cursor xcursor; if (cursor == frame->current_cursor) diff --git a/src/frames.c b/src/frames.c index 2805d9e0e..a99c13aa4 100644 --- a/src/frames.c +++ b/src/frames.c @@ -464,22 +464,20 @@ meta_frames_new (int screen_number) void meta_frames_manage_window (MetaFrames *frames, - Window xwindow) + Window xwindow, + GdkWindow *window) { MetaUIFrame *frame; + g_assert (window); + frame = g_new (MetaUIFrame, 1); - frame->window = gdk_window_foreign_new (xwindow); + frame->window = window; - if (frame->window == NULL) - { - g_free (frame); - meta_bug ("Frame 0x%lx doesn't exist\n", xwindow); - return; - } - gdk_window_set_user_data (frame->window, frames); + gtk_style_set_background (GTK_WIDGET (frames)->style, + frame->window, GTK_STATE_NORMAL); /* Don't set event mask here, it's in frame.c */ @@ -521,7 +519,7 @@ meta_frames_unmanage_window (MetaFrames *frames, g_hash_table_remove (frames->frames, &frame->xwindow); - g_object_unref (G_OBJECT (frame->window)); + gdk_window_destroy (frame->window); if (frame->layout) g_object_unref (G_OBJECT (frame->layout)); @@ -910,6 +908,25 @@ meta_frames_apply_shapes (MetaFrames *frames, #endif /* HAVE_SHAPE */ } +void +meta_frames_move_resize_frame (MetaFrames *frames, + Window xwindow, + int x, + int y, + int width, + int height) +{ + MetaUIFrame *frame = meta_frames_lookup_window (frames, xwindow); + int old_width, old_height; + + gdk_drawable_get_size (frame->window, &old_width, &old_height); + + gdk_window_move_resize (frame->window, x, y, width, height); + + if (old_width != width || old_height != height) + gdk_window_invalidate_rect (frame->window, NULL, FALSE); +} + void meta_frames_queue_draw (MetaFrames *frames, Window xwindow) @@ -1672,7 +1689,7 @@ meta_frames_expose_event (GtkWidget *widget, MetaFrames *frames; frames = META_FRAMES (widget); - + frame = meta_frames_lookup_window (frames, GDK_WINDOW_XID (event->window)); if (frame == NULL) return FALSE; diff --git a/src/frames.h b/src/frames.h index 182b6516e..13b4f9a8a 100644 --- a/src/frames.h +++ b/src/frames.h @@ -103,7 +103,8 @@ GType meta_frames_get_type (void) G_GNUC_CONST; MetaFrames *meta_frames_new (int screen_number); void meta_frames_manage_window (MetaFrames *frames, - Window xwindow); + Window xwindow, + GdkWindow *window); void meta_frames_unmanage_window (MetaFrames *frames, Window xwindow); void meta_frames_set_title (MetaFrames *frames, @@ -130,7 +131,12 @@ void meta_frames_apply_shapes (MetaFrames *frames, int new_window_width, int new_window_height, gboolean window_has_shape); - +void meta_frames_move_resize_frame (MetaFrames *frames, + Window xwindow, + int x, + int y, + int width, + int height); void meta_frames_queue_draw (MetaFrames *frames, Window xwindow); diff --git a/src/ui.c b/src/ui.c index eff54f27e..1f53c3b14 100644 --- a/src/ui.c +++ b/src/ui.c @@ -152,21 +152,78 @@ meta_ui_get_frame_geometry (MetaUI *ui, left_width, right_width); } - -void -meta_ui_add_frame (MetaUI *ui, - Window xwindow) +Window +meta_ui_create_frame_window (MetaUI *ui, + Display *xdisplay, + gint x, + gint y, + gint width, + gint height, + gint screen_no) { - meta_frames_manage_window (ui->frames, xwindow); + GdkDisplay *display = gdk_x11_lookup_xdisplay (xdisplay); + GdkScreen *screen = gdk_display_get_screen (display, screen_no); + GdkWindowAttr attrs; + gint attributes_mask; + GdkWindow *window; + + /* Default depth/visual handles clients with weird visuals; they can + * always be children of the root depth/visual obviously, but + * e.g. DRI games can't be children of a parent that has the same + * visual as the client. + */ + + attrs.title = NULL; + + /* frame.c is going to replace the event mask immediately, but + * we still have to set it here to let GDK know what it is. + */ + attrs.event_mask = + GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | + GDK_ENTER_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK | GDK_FOCUS_CHANGE_MASK; + attrs.x = x; + attrs.y = y; + attrs.wclass = GDK_INPUT_OUTPUT; + attrs.visual = gdk_screen_get_system_visual (screen); + attrs.colormap = gdk_screen_get_default_colormap (screen); + attrs.window_type = GDK_WINDOW_CHILD; + attrs.cursor = NULL; + attrs.wmclass_name = NULL; + attrs.wmclass_class = NULL; + attrs.override_redirect = FALSE; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP; + + window = + gdk_window_new (gdk_screen_get_root_window(screen), + &attrs, attributes_mask); + + gdk_window_resize (window, width, height); + + meta_frames_manage_window (ui->frames, GDK_WINDOW_XID (window), window); + + return GDK_WINDOW_XID (window); } void -meta_ui_remove_frame (MetaUI *ui, - Window xwindow) +meta_ui_destroy_frame_window (MetaUI *ui, + Window xwindow) { meta_frames_unmanage_window (ui->frames, xwindow); } +void +meta_ui_move_resize_frame (MetaUI *ui, + Window frame, + int x, + int y, + int width, + int height) +{ + meta_frames_move_resize_frame (ui->frames, frame, x, y, width, height); +} + void meta_ui_map_frame (MetaUI *ui, Window xwindow) @@ -713,12 +770,11 @@ meta_ui_window_is_widget (MetaUI *ui, window = gdk_xid_table_lookup (xwindow); - if (window && - gdk_window_get_window_type (window) != GDK_WINDOW_FOREIGN) + if (window) { void *user_data = NULL; gdk_window_get_user_data (window, &user_data); - return user_data != NULL; + return user_data != NULL && user_data != ui->frames; } else return FALSE; @@ -759,7 +815,7 @@ meta_stock_icons_init (void) icon_set = gtk_icon_set_new_from_pixbuf (pixbuf); gtk_icon_factory_add (factory, items[i].stock_id, icon_set); gtk_icon_set_unref (icon_set); - + g_object_unref (G_OBJECT (pixbuf)); } diff --git a/src/ui.h b/src/ui.h index 6ed690416..bdbb81465 100644 --- a/src/ui.h +++ b/src/ui.h @@ -54,11 +54,21 @@ void meta_ui_get_frame_geometry (MetaUI *ui, Window frame_xwindow, int *top_height, int *bottom_height, int *left_width, int *right_width); -void meta_ui_add_frame (MetaUI *ui, - Window xwindow); -void meta_ui_remove_frame (MetaUI *ui, - Window xwindow); - +Window meta_ui_create_frame_window (MetaUI *ui, + Display *xdisplay, + gint x, + gint y, + gint width, + gint height, + gint screen_no); +void meta_ui_destroy_frame_window (MetaUI *ui, + Window xwindow); +void meta_ui_move_resize_frame (MetaUI *ui, + Window frame, + int x, + int y, + int width, + int height); /* GDK insists on tracking map/unmap */ void meta_ui_map_frame (MetaUI *ui,