diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c index 1b4effa80f..94f380448a 100644 --- a/gdk/win32/gdksurface-win32.c +++ b/gdk/win32/gdksurface-win32.c @@ -653,6 +653,7 @@ _gdk_win32_display_create_surface (GdkDisplay *display, g_object_unref (frame_clock); impl->hdc = GetDC (impl->handle); + impl->inhibit_configure = TRUE; return surface; } @@ -1042,14 +1043,15 @@ gdk_win32_surface_do_move (GdkSurface *window, } void -gdk_win32_surface_resize (GdkSurface *window, - int width, int height) +gdk_win32_surface_resize (GdkSurface *surface, + int width, + int height) { RECT outer_rect; - g_return_if_fail (GDK_IS_SURFACE (window)); + g_return_if_fail (GDK_IS_SURFACE (surface)); - if (GDK_SURFACE_DESTROYED (window)) + if (GDK_SURFACE_DESTROYED (surface)) return; if (width < 1) @@ -1058,28 +1060,29 @@ gdk_win32_surface_resize (GdkSurface *window, height = 1; GDK_NOTE (MISC, g_print ("gdk_win32_surface_resize: %p: %dx%d\n", - GDK_SURFACE_HWND (window), width, height)); + GDK_SURFACE_HWND (surface), width, height)); - if (window->state & GDK_TOPLEVEL_STATE_FULLSCREEN) + if (surface->state & GDK_TOPLEVEL_STATE_FULLSCREEN) return; - get_outer_rect (window, width, height, &outer_rect); + get_outer_rect (surface, width, height, &outer_rect); GDK_NOTE (MISC, g_print ("... SetWindowPos(%p,NULL,0,0,%ld,%ld," "NOACTIVATE|NOMOVE|NOZORDER)\n", - GDK_SURFACE_HWND (window), + GDK_SURFACE_HWND (surface), outer_rect.right - outer_rect.left, outer_rect.bottom - outer_rect.top)); - API_CALL (SetWindowPos, (GDK_SURFACE_HWND (window), + API_CALL (SetWindowPos, (GDK_SURFACE_HWND (surface), SWP_NOZORDER_SPECIFIED, 0, 0, outer_rect.right - outer_rect.left, outer_rect.bottom - outer_rect.top, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOZORDER)); - window->resize_count += 1; + surface->resize_count += 1; - gdk_surface_request_layout (window); + if (!GDK_WIN32_SURFACE (surface)->force_recompute_size) + gdk_surface_request_layout (surface); } static void @@ -2495,35 +2498,41 @@ _gdk_win32_surface_handle_aerosnap (GdkSurface *window, } static void -apply_snap (GdkSurface *window, - GdkWin32AeroSnapState snap) +apply_snap (GdkSurface *surface, + GdkWin32AeroSnapState snap) { GdkMonitor *monitor; GdkDisplay *display; - display = gdk_surface_get_display (window); - monitor = gdk_display_get_monitor_at_surface (display, window); + display = gdk_surface_get_display (surface); + monitor = gdk_display_get_monitor_at_surface (display, surface); switch (snap) { case GDK_WIN32_AEROSNAP_STATE_UNDETERMINED: break; case GDK_WIN32_AEROSNAP_STATE_MAXIMIZE: - unsnap (window, monitor); - gdk_win32_surface_maximize (window); + unsnap (surface, monitor); + gdk_win32_surface_maximize (surface); break; case GDK_WIN32_AEROSNAP_STATE_HALFLEFT: - unsnap (window, monitor); - snap_left (window, monitor, monitor); + unsnap (surface, monitor); + snap_left (surface, monitor, monitor); break; case GDK_WIN32_AEROSNAP_STATE_HALFRIGHT: - unsnap (window, monitor); - snap_right (window, monitor, monitor); + unsnap (surface, monitor); + snap_right (surface, monitor, monitor); break; case GDK_WIN32_AEROSNAP_STATE_FULLUP: - snap_up (window); + snap_up (surface); break; } + + if (snap != GDK_WIN32_AEROSNAP_STATE_UNDETERMINED) + { + GDK_WIN32_SURFACE (surface)->inhibit_configure = TRUE; + GDK_WIN32_SURFACE (surface)->force_recompute_size = FALSE; + } } /* Registers a dumb window class. This window @@ -3403,10 +3412,10 @@ get_cursor_name_from_op (GdkW32WindowDragOp op, } static void -setup_drag_move_resize_context (GdkSurface *window, +setup_drag_move_resize_context (GdkSurface *surface, GdkW32DragMoveResizeContext *context, GdkW32WindowDragOp op, - GdkSurfaceEdge edge, + GdkSurfaceEdge edge, GdkDevice *device, int button, double x, @@ -3415,12 +3424,13 @@ setup_drag_move_resize_context (GdkSurface *window, { RECT rect; const char *cursor_name; - GdkSurface *pointer_window; - GdkWin32Surface *impl = GDK_WIN32_SURFACE (window); - gboolean maximized = gdk_toplevel_get_state (GDK_TOPLEVEL (window)) & GDK_TOPLEVEL_STATE_MAXIMIZED; + GdkSurface *pointer_surface; + GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); + gboolean maximized = gdk_toplevel_get_state (GDK_TOPLEVEL (surface)) & GDK_TOPLEVEL_STATE_MAXIMIZED; int root_x, root_y; + gboolean restore_configure = FALSE; - gdk_win32_surface_get_root_coords (window, x, y, &root_x, &root_y); + gdk_win32_surface_get_root_coords (surface, x, y, &root_x, &root_y); /* Before we drag, we need to undo any maximization or snapping. * AeroSnap behaviour: @@ -3443,7 +3453,7 @@ setup_drag_move_resize_context (GdkSurface *window, * resize * don't unsnap * apply new width and x position to unsnapped cache, - * so that unsnapped window only regains its height + * so that unsnapped surface only regains its height * and y position, but inherits x and width from * the fullup snapped state * vertical resize: @@ -3458,7 +3468,7 @@ setup_drag_move_resize_context (GdkSurface *window, * * TODO: make this implementation behave as AeroSnap on resizes? * There's also the case where - * a halfleft/halfright window isn't unsnapped when it's + * a halfleft/halfright surface isn't unsnapped when it's * being moved horizontally, but it's more difficult to implement. */ if (op == GDK_WIN32_DRAGOP_RESIZE && @@ -3466,7 +3476,8 @@ setup_drag_move_resize_context (GdkSurface *window, impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFLEFT || impl->snap_state == GDK_WIN32_AEROSNAP_STATE_FULLUP)) { - discard_snapinfo (window); + discard_snapinfo (surface); + restore_configure = TRUE; } else if (maximized || (impl->snap_state == GDK_WIN32_AEROSNAP_STATE_HALFRIGHT || @@ -3476,24 +3487,25 @@ setup_drag_move_resize_context (GdkSurface *window, GdkMonitor *monitor; int wx, wy, wwidth, wheight; int swx, swy, swwidth, swheight; - gboolean pointer_outside_of_window; + gboolean pointer_outside_of_surface; int offsetx, offsety; gboolean left_half; GdkDisplay *display; - display = gdk_surface_get_display (window); - monitor = gdk_display_get_monitor_at_surface (display, window); - gdk_surface_get_geometry (window, &wx, &wy, &wwidth, &wheight); + restore_configure = TRUE; + display = gdk_surface_get_display (surface); + monitor = gdk_display_get_monitor_at_surface (display, surface); + gdk_surface_get_geometry (surface, &wx, &wy, &wwidth, &wheight); swx = wx; swy = wy; swwidth = wwidth; swheight = wheight; - /* Subtract window shadow. We don't want pointer to go outside of - * the visible window during drag-move. For drag-resize it's OK. - * Don't take shadow into account if the window is maximized - - * maximized windows don't have shadows. + /* Subtract surface shadow. We don't want pointer to go outside of + * the visible surface during drag-move. For drag-resize it's OK. + * Don't take shadow into account if the surface is maximized - + * maximized surfaces don't have shadows. */ if (op == GDK_WIN32_DRAGOP_MOVE && !maximized) { @@ -3503,16 +3515,16 @@ setup_drag_move_resize_context (GdkSurface *window, swheight -= impl->shadow_y; } - pointer_outside_of_window = root_x < swx || root_x > swx + swwidth || + pointer_outside_of_surface = root_x < swx || root_x > swx + swwidth || root_y < swy || root_y > swy + swheight; - /* Calculate the offset of the pointer relative to the window */ + /* Calculate the offset of the pointer relative to the surface */ offsetx = root_x - swx; offsety = root_y - swy; - /* Figure out in which half of the window the pointer is. + /* Figure out in which half of the surface the pointer is. * The code currently only concerns itself with horizontal * dimension (left/right halves). - * There's no upper/lower half, because usually window + * There's no upper/lower half, because usually surface * is dragged by its upper half anyway. If that changes, adjust * accordingly. */ @@ -3522,26 +3534,26 @@ setup_drag_move_resize_context (GdkSurface *window, if (!left_half) offsetx = swwidth - offsetx; - GDK_NOTE (MISC, g_print ("Pointer at %d : %d, this is %d : %d relative to the window's %s\n", + GDK_NOTE (MISC, g_print ("Pointer at %d : %d, this is %d : %d relative to the surface's %s\n", root_x, root_y, offsetx, offsety, left_half ? "left half" : "right half")); - /* Move window in such a way that on unmaximization/unsnapping the pointer - * is still pointing at the appropriate half of the window, + /* Move surface in such a way that on unmaximization/unsnapping the pointer + * is still pointing at the appropriate half of the surface, * with the same offset from the left or right edge. If the new - * window size is too small, and adding that offset puts the pointer + * surface size is too small, and adding that offset puts the pointer * into the other half or even beyond, move the pointer to the middle. */ - if (!pointer_outside_of_window && maximized) + if (!pointer_outside_of_surface && maximized) { WINDOWPLACEMENT placement; int unmax_width, unmax_height; int shadow_unmax_width, shadow_unmax_height; placement.length = sizeof (placement); - API_CALL (GetWindowPlacement, (GDK_SURFACE_HWND (window), &placement)); + API_CALL (GetWindowPlacement, (GDK_SURFACE_HWND (surface), &placement)); - GDK_NOTE (MISC, g_print ("W32 WM unmaximized window placement is %ld x %ld @ %ld : %ld\n", + GDK_NOTE (MISC, g_print ("W32 WM unmaximized surface placement is %ld x %ld @ %ld : %ld\n", placement.rcNormalPosition.right - placement.rcNormalPosition.left, placement.rcNormalPosition.bottom - placement.rcNormalPosition.top, placement.rcNormalPosition.left, @@ -3587,9 +3599,9 @@ setup_drag_move_resize_context (GdkSurface *window, placement.rcNormalPosition.left, placement.rcNormalPosition.top)); - API_CALL (SetWindowPlacement, (GDK_SURFACE_HWND (window), &placement)); + API_CALL (SetWindowPlacement, (GDK_SURFACE_HWND (surface), &placement)); } - else if (!pointer_outside_of_window && impl->snap_stash_int) + else if (!pointer_outside_of_surface && impl->snap_stash_int) { GdkRectangle new_pos; GdkRectangle snew_pos; @@ -3619,22 +3631,22 @@ setup_drag_move_resize_context (GdkSurface *window, new_pos.y = root_y - new_pos.height / 2; } - GDK_NOTE (MISC, g_print ("Unsnapped window to %d : %d\n", + GDK_NOTE (MISC, g_print ("Unsnapped surface to %d : %d\n", new_pos.x, new_pos.y)); - discard_snapinfo (window); - gdk_win32_surface_move_resize (window, new_pos.x, new_pos.y, + discard_snapinfo (surface); + gdk_win32_surface_move_resize (surface, new_pos.x, new_pos.y, new_pos.width, new_pos.height); } if (maximized) - gdk_win32_surface_unmaximize (window); + gdk_win32_surface_unmaximize (surface); else - unsnap (window, monitor); + unsnap (surface, monitor); - if (pointer_outside_of_window) + if (pointer_outside_of_surface) { - /* Pointer outside of the window, move pointer into window */ + /* Pointer outside of the surface, move pointer into surface */ GDK_NOTE (MISC, g_print ("Pointer at %d : %d is outside of %d x %d @ %d : %d, move it to %d : %d\n", root_x, root_y, wwidth, wheight, wx, wy, wx + wwidth / 2, wy + wheight / 2)); root_x = wx + wwidth / 2; @@ -3647,26 +3659,29 @@ setup_drag_move_resize_context (GdkSurface *window, } } - _gdk_win32_get_window_rect (window, &rect); + if (restore_configure) + impl->inhibit_configure = FALSE; + + _gdk_win32_get_window_rect (surface, &rect); cursor_name = get_cursor_name_from_op (op, edge); context->cursor = gdk_cursor_new_from_name (cursor_name, NULL); - pointer_window = window; + pointer_surface = surface; /* Note: This triggers a WM_CAPTURECHANGED, which will trigger * gdk_win32_surface_end_move_resize_drag(), which will end * our op before it even begins, but only if context->op is not NONE. * This is why we first do the grab, *then* set the op. */ - gdk_device_grab (device, pointer_window, + gdk_device_grab (device, pointer_surface, FALSE, GDK_ALL_EVENTS_MASK, context->cursor, timestamp); - context->window = g_object_ref (window); + context->window = g_object_ref (surface); context->op = op; context->edge = edge; context->device = device; @@ -3686,10 +3701,10 @@ setup_drag_move_resize_context (GdkSurface *window, calculate_aerosnap_regions (context); GDK_NOTE (EVENTS, - g_print ("begin drag moveresize: window %p, toplevel %p, " + g_print ("begin drag moveresize: surface %p, toplevel %p, " "op %u, edge %d, device %p, " "button %d, coord %d:%d, time %u\n", - pointer_window, window, + pointer_surface, surface, context->op, context->edge, context->device, context->button, context->start_root_x, context->start_root_y, context->timestamp)); @@ -4084,45 +4099,61 @@ gdk_win32_surface_minimize (GdkSurface *window) } static void -gdk_win32_surface_maximize (GdkSurface *window) +gdk_win32_surface_maximize (GdkSurface *surface) { - g_return_if_fail (GDK_IS_SURFACE (window)); + GdkWin32Surface *impl; - if (GDK_SURFACE_DESTROYED (window)) + g_return_if_fail (GDK_IS_SURFACE (surface)); + + if (GDK_SURFACE_DESTROYED (surface)) return; GDK_NOTE (MISC, g_print ("gdk_surface_maximize: %p: %s\n", - GDK_SURFACE_HWND (window), - _gdk_win32_surface_state_to_string (window->state))); + GDK_SURFACE_HWND (surface), + _gdk_win32_surface_state_to_string (surface->state))); - if (GDK_SURFACE_IS_MAPPED (window)) - GtkShowWindow (window, SW_MAXIMIZE); + impl = GDK_WIN32_SURFACE (surface); + impl->inhibit_configure = TRUE; + impl->force_recompute_size = FALSE; + + if (GDK_SURFACE_IS_MAPPED (surface)) + GtkShowWindow (surface, SW_MAXIMIZE); else - gdk_synthesize_surface_state (window, + gdk_synthesize_surface_state (surface, 0, GDK_TOPLEVEL_STATE_MAXIMIZED); } static void -gdk_win32_surface_unmaximize (GdkSurface *window) +gdk_win32_surface_unmaximize (GdkSurface *surface) { - g_return_if_fail (GDK_IS_SURFACE (window)); + GdkWin32Surface *impl; - if (GDK_SURFACE_DESTROYED (window)) + g_return_if_fail (GDK_IS_SURFACE (surface)); + + if (GDK_SURFACE_DESTROYED (surface)) return; GDK_NOTE (MISC, g_print ("gdk_surface_unmaximize: %p: %s\n", - GDK_SURFACE_HWND (window), - _gdk_win32_surface_state_to_string (window->state))); + GDK_SURFACE_HWND (surface), + _gdk_win32_surface_state_to_string (surface->state))); - _gdk_win32_surface_invalidate_egl_framebuffer (window); + _gdk_win32_surface_invalidate_egl_framebuffer (surface); - if (GDK_SURFACE_IS_MAPPED (window)) - GtkShowWindow (window, SW_RESTORE); + if (GDK_SURFACE_IS_MAPPED (surface)) + GtkShowWindow (surface, SW_RESTORE); else - gdk_synthesize_surface_state (window, + gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0); + + impl = GDK_WIN32_SURFACE (surface); + + if (impl->inhibit_configure) + { + impl->inhibit_configure = FALSE; + impl->force_recompute_size = TRUE; + } } static void @@ -4547,6 +4578,9 @@ _gdk_win32_surface_request_layout (GdkSurface *surface) &surface->x, &surface->y, NULL, NULL); } + + if (!impl->inhibit_configure) + impl->force_recompute_size = TRUE; } } @@ -4561,8 +4595,18 @@ _gdk_win32_surface_compute_size (GdkSurface *surface) if (!impl->drag_move_resize_context.native_move_resize_pending) { - surface->width = impl->next_layout.configured_width; - surface->height = impl->next_layout.configured_height; + if (GDK_IS_TOPLEVEL (surface) && impl->force_recompute_size) + { + surface->width = width; + surface->height = height; + gdk_win32_surface_resize (surface, width, height); + impl->force_recompute_size = FALSE; + } + else + { + surface->width = impl->next_layout.configured_width; + surface->height = impl->next_layout.configured_height; + } _gdk_surface_update_size (surface); } diff --git a/gdk/win32/gdksurface-win32.h b/gdk/win32/gdksurface-win32.h index be3fe4a74a..08bd0a20b7 100644 --- a/gdk/win32/gdksurface-win32.h +++ b/gdk/win32/gdksurface-win32.h @@ -337,6 +337,7 @@ struct _GdkWin32Surface int configured_height; RECT configured_rect; } next_layout; + gboolean force_recompute_size; #ifdef HAVE_EGL guint egl_force_redraw_all : 1;