GDK W32: custom (non-WM) drag-move and drag-resize code

Normally works only on CSD windows, non-CSD windows continue
to use WM modal loop for drag-resizing and drag-moving. However,
if it is activated on non-CSD windows, it does work.

Has the advantage of being completely immune to AeroSnap.
AeroSnap only worked partially on CSD windows, with the only part
that worked being "don't let users drag window titlebar outside of
the desktop". Now AeroSnap doesn't work on windows moved by
this code at all, which is good, since they currently don't work
well with it due to the way shadows are drawn.

It's possible to also re-implement AeroSnap (or something similar),
but that is a story for another commit.

This code was originally intended to fix the problem of window
size and window contents desynchronization, but failed to achieve
that result in the end. Nevertheless, it serves as a foundation for
other changes to the way window resizing works.

https://bugzilla.gnome.org/show_bug.cgi?id=761629
This commit is contained in:
Руслан Ижбулатов 2016-02-06 12:06:41 +00:00
parent 597151c736
commit e03946bd28
4 changed files with 525 additions and 151 deletions

View File

@ -1408,8 +1408,14 @@ doesnt_want_char (gint mask,
return !(mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK));
}
void
_gdk_win32_emit_configure_event (GdkWindow *window)
/* Acquires actual client area size of the underlying native window.
* Rectangle is in GDK screen coordinates (_gdk_offset_* is added).
* Returns FALSE if configure events should be inhibited,
* TRUE otherwise.
*/
gboolean
_gdk_win32_get_window_rect (GdkWindow *window,
RECT *rect)
{
GdkWindowImplWin32 *window_impl;
RECT client_rect;
@ -1417,8 +1423,6 @@ _gdk_win32_emit_configure_event (GdkWindow *window)
HWND hwnd;
window_impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (window_impl->inhibit_configure)
return;
hwnd = GDK_WINDOW_HWND (window);
@ -1434,11 +1438,23 @@ _gdk_win32_emit_configure_event (GdkWindow *window)
point.y += _gdk_offset_y;
}
window->width = client_rect.right - client_rect.left;
window->height = client_rect.bottom - client_rect.top;
rect->left = point.x;
rect->top = point.y;
rect->right = point.x + client_rect.right - client_rect.left;
rect->bottom = point.y + client_rect.bottom - client_rect.top;
window->x = point.x;
window->y = point.y;
return !window_impl->inhibit_configure;
}
void
_gdk_win32_do_emit_configure_event (GdkWindow *window,
RECT rect)
{
window->width = rect.right - rect.left;
window->height = rect.bottom - rect.top;
window->x = rect.left;
window->y = rect.top;
_gdk_window_update_size (window);
@ -1448,16 +1464,27 @@ _gdk_win32_emit_configure_event (GdkWindow *window)
event->configure.window = window;
event->configure.width = client_rect.right - client_rect.left;
event->configure.height = client_rect.bottom - client_rect.top;
event->configure.width = rect.right - rect.left;
event->configure.height = rect.bottom - rect.top;
event->configure.x = point.x;
event->configure.y = point.y;
event->configure.x = rect.left;
event->configure.y = rect.top;
_gdk_win32_append_event (event);
}
}
void
_gdk_win32_emit_configure_event (GdkWindow *window)
{
RECT rect;
if (!_gdk_win32_get_window_rect (window, &rect))
return;
_gdk_win32_do_emit_configure_event (window, rect);
}
cairo_region_t *
_gdk_win32_hrgn_to_region (HRGN hrgn)
{
@ -1874,6 +1901,76 @@ ensure_stacking_on_activate_app (MSG *msg,
}
}
gboolean
_gdk_win32_window_fill_min_max_info (GdkWindow *window,
MINMAXINFO *mmi)
{
GdkWindowImplWin32 *impl;
RECT rect;
if (GDK_WINDOW_DESTROYED (window))
return FALSE;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (impl->hint_flags & GDK_HINT_MIN_SIZE)
{
rect.left = rect.top = 0;
rect.right = impl->hints.min_width;
rect.bottom = impl->hints.min_height;
_gdk_win32_adjust_client_rect (window, &rect);
mmi->ptMinTrackSize.x = rect.right - rect.left;
mmi->ptMinTrackSize.y = rect.bottom - rect.top;
}
if (impl->hint_flags & GDK_HINT_MAX_SIZE)
{
int maxw, maxh;
rect.left = rect.top = 0;
rect.right = impl->hints.max_width;
rect.bottom = impl->hints.max_height;
_gdk_win32_adjust_client_rect (window, &rect);
/* at least on win9x we have the 16 bit trouble */
maxw = rect.right - rect.left;
maxh = rect.bottom - rect.top;
mmi->ptMaxTrackSize.x = maxw > 0 && maxw < G_MAXSHORT ? maxw : G_MAXSHORT;
mmi->ptMaxTrackSize.y = maxh > 0 && maxh < G_MAXSHORT ? maxh : G_MAXSHORT;
}
else
{
HMONITOR nearest_monitor;
MONITORINFO nearest_info;
nearest_monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
nearest_info.cbSize = sizeof (nearest_info);
if (GetMonitorInfoA (nearest_monitor, &nearest_info))
{
/* MSDN says that we must specify maximized window
* size as if it was located on the primary monitor.
* However, we still need to account for a taskbar
* that might or might not be on the nearest monitor where
* window will actually end up.
* "0" here is the top-left corner of the primary monitor.
*/
mmi->ptMaxPosition.x = 0 + (nearest_info.rcWork.left - nearest_info.rcMonitor.left);
mmi->ptMaxPosition.y = 0 + (nearest_info.rcWork.top - nearest_info.rcMonitor.top);
mmi->ptMaxSize.x = nearest_info.rcWork.right - nearest_info.rcWork.left;
mmi->ptMaxSize.y = nearest_info.rcWork.bottom - nearest_info.rcWork.top;
}
mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXMAXTRACK);
mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYMAXTRACK);
}
return TRUE;
}
#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \
GDK_BUTTON2_MASK | \
GDK_BUTTON3_MASK | \
@ -1887,7 +1984,6 @@ gdk_event_translate (MSG *msg,
RECT rect, *drag, orig_drag;
POINT point;
MINMAXINFO *mmi;
LONG style;
HWND hwnd;
GdkCursor *cursor;
BYTE key_state[256];
@ -2469,7 +2565,13 @@ gdk_event_translate (MSG *msg,
current_root_x = msg->pt.x + _gdk_offset_x;
current_root_y = msg->pt.y + _gdk_offset_y;
if (!_gdk_input_ignore_core)
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
{
gdk_win32_window_do_move_resize_drag (window, current_root_x, current_root_y);
}
else if (!_gdk_input_ignore_core)
{
event = gdk_event_new (GDK_MOTION_NOTIFY);
event->motion.window = window;
@ -2775,6 +2877,11 @@ gdk_event_translate (MSG *msg,
_modal_move_resize_window = NULL;
_gdk_win32_end_modal_call ();
}
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
gdk_win32_window_end_move_resize_drag (window);
break;
case WM_WINDOWPOSCHANGING:
@ -3130,11 +3237,8 @@ gdk_event_translate (MSG *msg,
break;
case WM_GETMINMAXINFO:
if (GDK_WINDOW_DESTROYED (window))
break;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
mmi = (MINMAXINFO*) msg->lParam;
GDK_NOTE (EVENTS, g_print (" (mintrack:%ldx%ld maxtrack:%ldx%ld "
"maxpos:%+ld%+ld maxsize:%ldx%ld)",
mmi->ptMinTrackSize.x, mmi->ptMinTrackSize.y,
@ -3142,79 +3246,20 @@ gdk_event_translate (MSG *msg,
mmi->ptMaxPosition.x, mmi->ptMaxPosition.y,
mmi->ptMaxSize.x, mmi->ptMaxSize.y));
style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE);
if (_gdk_win32_window_fill_min_max_info (window, mmi))
{
/* Don't call DefWindowProcW() */
GDK_NOTE (EVENTS,
g_print (" (handled, mintrack:%ldx%ld maxtrack:%ldx%ld "
"maxpos:%+ld%+ld maxsize:%ldx%ld)",
mmi->ptMinTrackSize.x, mmi->ptMinTrackSize.y,
mmi->ptMaxTrackSize.x, mmi->ptMaxTrackSize.y,
mmi->ptMaxPosition.x, mmi->ptMaxPosition.y,
mmi->ptMaxSize.x, mmi->ptMaxSize.y));
if (impl->hint_flags & GDK_HINT_MIN_SIZE)
{
rect.left = rect.top = 0;
rect.right = impl->hints.min_width;
rect.bottom = impl->hints.min_height;
return_val = TRUE;
}
_gdk_win32_adjust_client_rect (window, &rect);
mmi->ptMinTrackSize.x = rect.right - rect.left;
mmi->ptMinTrackSize.y = rect.bottom - rect.top;
}
if (impl->hint_flags & GDK_HINT_MAX_SIZE)
{
int maxw, maxh;
rect.left = rect.top = 0;
rect.right = impl->hints.max_width;
rect.bottom = impl->hints.max_height;
_gdk_win32_adjust_client_rect (window, &rect);
/* at least on win9x we have the 16 bit trouble */
maxw = rect.right - rect.left;
maxh = rect.bottom - rect.top;
mmi->ptMaxTrackSize.x = maxw > 0 && maxw < G_MAXSHORT ? maxw : G_MAXSHORT;
mmi->ptMaxTrackSize.y = maxh > 0 && maxh < G_MAXSHORT ? maxh : G_MAXSHORT;
}
/* Assume that these styles are incompatible with CSD,
* so there's no reason for us to override the defaults.
*/
else if ((style & (WS_BORDER | WS_THICKFRAME)) == 0)
{
HMONITOR nearest_monitor;
MONITORINFO nearest_info;
nearest_monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST);
nearest_info.cbSize = sizeof (nearest_info);
if (GetMonitorInfoA (nearest_monitor, &nearest_info))
{
/* MSDN says that we must specify maximized window
* size as if it was located on the primary monitor.
* However, we still need to account for a taskbar
* that might or might not be on the nearest monitor where
* window will actually end up.
* "0" here is the top-left corner of the primary monitor.
*/
mmi->ptMaxPosition.x = 0 + (nearest_info.rcWork.left - nearest_info.rcMonitor.left);
mmi->ptMaxPosition.y = 0 + (nearest_info.rcWork.top - nearest_info.rcMonitor.top);
mmi->ptMaxSize.x = nearest_info.rcWork.right - nearest_info.rcWork.left;
mmi->ptMaxSize.y = nearest_info.rcWork.bottom - nearest_info.rcWork.top;
}
mmi->ptMaxTrackSize.x = GetSystemMetrics (SM_CXMAXTRACK);
mmi->ptMaxTrackSize.y = GetSystemMetrics (SM_CYMAXTRACK);
}
if (impl->hint_flags & (GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE))
{
/* Don't call DefWindowProcW() */
GDK_NOTE (EVENTS, g_print (" (handled, mintrack:%ldx%ld maxtrack:%ldx%ld "
"maxpos:%+ld%+ld maxsize:%ldx%ld)",
mmi->ptMinTrackSize.x, mmi->ptMinTrackSize.y,
mmi->ptMaxTrackSize.x, mmi->ptMaxTrackSize.y,
mmi->ptMaxPosition.x, mmi->ptMaxPosition.y,
mmi->ptMaxSize.x, mmi->ptMaxSize.y));
return_val = TRUE;
}
return_val = TRUE;
break;
case WM_CLOSE:

View File

@ -521,8 +521,20 @@ gchar *_gdk_win32_display_manager_get_atom_name (GdkDisplayManager *manager,
void _gdk_win32_append_event (GdkEvent *event);
void _gdk_win32_emit_configure_event (GdkWindow *window);
guint32 _gdk_win32_keymap_get_decimal_mark (void);
gboolean _gdk_win32_get_window_rect (GdkWindow *window,
RECT *rect);
void _gdk_win32_do_emit_configure_event (GdkWindow *window,
RECT rect);
void gdk_win32_window_do_move_resize_drag (GdkWindow *window,
gint x,
gint y);
void gdk_win32_window_end_move_resize_drag (GdkWindow *window);
gboolean _gdk_win32_window_fill_min_max_info (GdkWindow *window,
MINMAXINFO *mmi);
/* Initialization */
void _gdk_win32_windowing_init (void);
void _gdk_dnd_init (void);

View File

@ -184,6 +184,50 @@ gdk_window_impl_win32_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
static void
gdk_win32_window_end_paint (GdkWindow *window)
{
GdkWindowImplWin32 *impl;
RECT window_rect;
gint x, y;
if (window == NULL || GDK_WINDOW_DESTROYED (window))
return;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
if (!impl->drag_move_resize_context.native_move_resize_pending)
return;
impl->drag_move_resize_context.native_move_resize_pending = FALSE;
gdk_window_get_position (window, &x, &y);
window_rect.left = x;
window_rect.top = y;
window_rect.right = window_rect.left + gdk_window_get_width (window);
window_rect.bottom = window_rect.top + gdk_window_get_height (window);
/* Turn client area into window area */
_gdk_win32_adjust_client_rect (window, &window_rect);
/* Convert GDK screen coordinates to W32 desktop coordinates */
window_rect.left -= _gdk_offset_x;
window_rect.right -= _gdk_offset_x;
window_rect.top -= _gdk_offset_y;
window_rect.bottom -= _gdk_offset_y;
GDK_NOTE (EVENTS, g_print ("Setting window position ... "));
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
SWP_NOZORDER_SPECIFIED,
window_rect.left, window_rect.top,
window_rect.right - window_rect.left,
window_rect.bottom - window_rect.top,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOREDRAW));
GDK_NOTE (EVENTS, g_print (" ... set window position\n"));
}
void
_gdk_win32_adjust_client_rect (GdkWindow *window,
RECT *rect)
@ -2639,19 +2683,272 @@ _gdk_window_get_functions (GdkWindow *window,
}
static void
gdk_win32_window_begin_resize_drag (GdkWindow *window,
GdkWindowEdge edge,
GdkDevice *device,
gint button,
gint root_x,
gint root_y,
guint32 timestamp)
setup_drag_move_resize_context (GdkWindow *window,
GdkW32DragMoveResizeContext *context,
GdkW32WindowDragOp op,
GdkWindowEdge edge,
GdkDevice *device,
gint button,
gint root_x,
gint root_y,
guint32 timestamp)
{
WPARAM winedge;
RECT rect;
_gdk_win32_get_window_rect (window, &rect);
context->op = op;
context->edge = edge;
context->device = device;
context->button = button;
context->start_root_x = root_x;
context->start_root_y = root_y;
context->timestamp = timestamp;
context->start_rect = rect;
GDK_NOTE (EVENTS,
g_print ("begin drag moveresize: "
"op %u, edge %d, device %p, "
"button %d, coord %d:%d, time %u\n",
context->op, context->edge, context->device,
context->button, context->start_root_x,
context->start_root_y, context->timestamp));
}
void
gdk_win32_window_end_move_resize_drag (GdkWindow *window)
{
GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
GdkW32DragMoveResizeContext *context = &impl->drag_move_resize_context;
context->op = GDK_WIN32_DRAGOP_NONE;
GDK_NOTE (EVENTS,
g_print ("end drag moveresize: "
"op %u, edge %d, device %p, "
"button %d, coord %d:%d, time %u\n",
context->op, context->edge, context->device,
context->button, context->start_root_x,
context->start_root_y, context->timestamp));
}
void
gdk_win32_window_do_move_resize_drag (GdkWindow *window,
gint x,
gint y)
{
RECT rect;
RECT new_rect;
gint diffy, diffx;
MINMAXINFO mmi;
GdkWindowImplWin32 *impl;
GdkW32DragMoveResizeContext *context;
gint width;
gint height;
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
context = &impl->drag_move_resize_context;
if (!_gdk_win32_get_window_rect (window, &rect))
return;
new_rect = context->start_rect;
diffx = x - context->start_root_x;
diffy = y - context->start_root_y;
switch (context->op)
{
case GDK_WIN32_DRAGOP_RESIZE:
switch (context->edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
new_rect.left += diffx;
new_rect.top += diffy;
break;
case GDK_WINDOW_EDGE_NORTH:
new_rect.top += diffy;
break;
case GDK_WINDOW_EDGE_NORTH_EAST:
new_rect.right += diffx;
new_rect.top += diffy;
break;
case GDK_WINDOW_EDGE_WEST:
new_rect.left += diffx;
break;
case GDK_WINDOW_EDGE_EAST:
new_rect.right += diffx;
break;
case GDK_WINDOW_EDGE_SOUTH_WEST:
new_rect.left += diffx;
new_rect.bottom += diffy;
break;
case GDK_WINDOW_EDGE_SOUTH:
new_rect.bottom += diffy;
break;
case GDK_WINDOW_EDGE_SOUTH_EAST:
default:
new_rect.right += diffx;
new_rect.bottom += diffy;
break;
}
/* When handling WM_GETMINMAXINFO, mmi is already populated
* by W32 WM and we apply our stuff on top of that.
* Here it isn't, so we should at least clear it.
*/
memset (&mmi, 0, sizeof (mmi));
if (!_gdk_win32_window_fill_min_max_info (window, &mmi))
break;
width = new_rect.right - new_rect.left;
height = new_rect.bottom - new_rect.top;
if (width > mmi.ptMaxTrackSize.x)
{
switch (context->edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
case GDK_WINDOW_EDGE_WEST:
case GDK_WINDOW_EDGE_SOUTH_WEST:
new_rect.left = new_rect.right - mmi.ptMaxTrackSize.x;
break;
case GDK_WINDOW_EDGE_NORTH_EAST:
case GDK_WINDOW_EDGE_EAST:
case GDK_WINDOW_EDGE_SOUTH_EAST:
default:
new_rect.right = new_rect.left + mmi.ptMaxTrackSize.x;
break;
}
}
else if (width < mmi.ptMinTrackSize.x)
{
switch (context->edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
case GDK_WINDOW_EDGE_WEST:
case GDK_WINDOW_EDGE_SOUTH_WEST:
new_rect.left = new_rect.right - mmi.ptMinTrackSize.x;
break;
case GDK_WINDOW_EDGE_NORTH_EAST:
case GDK_WINDOW_EDGE_EAST:
case GDK_WINDOW_EDGE_SOUTH_EAST:
default:
new_rect.right = new_rect.left + mmi.ptMinTrackSize.x;
break;
}
}
if (height > mmi.ptMaxTrackSize.y)
{
switch (context->edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
case GDK_WINDOW_EDGE_NORTH:
case GDK_WINDOW_EDGE_NORTH_EAST:
new_rect.top = new_rect.bottom - mmi.ptMaxTrackSize.y;
case GDK_WINDOW_EDGE_SOUTH_WEST:
case GDK_WINDOW_EDGE_SOUTH:
case GDK_WINDOW_EDGE_SOUTH_EAST:
default:
new_rect.bottom = new_rect.top + mmi.ptMaxTrackSize.y;
break;
}
}
else if (height < mmi.ptMinTrackSize.y)
{
switch (context->edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
case GDK_WINDOW_EDGE_NORTH:
case GDK_WINDOW_EDGE_NORTH_EAST:
new_rect.top = new_rect.bottom - mmi.ptMinTrackSize.y;
case GDK_WINDOW_EDGE_SOUTH_WEST:
case GDK_WINDOW_EDGE_SOUTH:
case GDK_WINDOW_EDGE_SOUTH_EAST:
default:
new_rect.bottom = new_rect.top + mmi.ptMinTrackSize.y;
break;
}
}
break;
case GDK_WIN32_DRAGOP_MOVE:
new_rect.left += diffx;
new_rect.top += diffy;
new_rect.right += diffx;
new_rect.bottom += diffy;
break;
default:
break;
}
if (context->op == GDK_WIN32_DRAGOP_RESIZE &&
(rect.left != new_rect.left ||
rect.right != new_rect.right ||
rect.top != new_rect.top ||
rect.bottom != new_rect.bottom))
{
context->native_move_resize_pending = TRUE;
_gdk_win32_do_emit_configure_event (window, new_rect);
}
else if (context->op == GDK_WIN32_DRAGOP_MOVE &&
(rect.left != new_rect.left ||
rect.top != new_rect.top))
{
POINT window_position;
context->native_move_resize_pending = FALSE;
_gdk_win32_do_emit_configure_event (window, new_rect);
/* Turn client area into window area */
_gdk_win32_adjust_client_rect (window, &new_rect);
/* Convert GDK screen coordinates to W32 desktop coordinates */
new_rect.left -= _gdk_offset_x;
new_rect.right -= _gdk_offset_x;
new_rect.top -= _gdk_offset_y;
new_rect.bottom -= _gdk_offset_y;
window_position.x = new_rect.left;
window_position.y = new_rect.top;
/* Move immediately, no need to wait for redraw */
API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window),
SWP_NOZORDER_SPECIFIED,
window_position.x, window_position.y,
0, 0,
SWP_NOACTIVATE | SWP_NOZORDER | SWP_NOSIZE));
}
}
static void
gdk_win32_window_begin_resize_drag (GdkWindow *window,
GdkWindowEdge edge,
GdkDevice *device,
gint button,
gint root_x,
gint root_y,
guint32 timestamp)
{
GdkWindowImplWin32 *impl;
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
if (GDK_WINDOW_DESTROYED (window) ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
IsIconic (GDK_WINDOW_HWND (window)))
return;
/* Tell Windows to start interactively resizing the window by pretending that
@ -2663,62 +2960,31 @@ gdk_win32_window_begin_resize_drag (GdkWindow *window,
if (button != 1)
return;
/* Must break the automatic grab that occured when the button was
* pressed, otherwise it won't work.
*/
gdk_device_ungrab (device, 0);
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
switch (edge)
{
case GDK_WINDOW_EDGE_NORTH_WEST:
winedge = HTTOPLEFT;
break;
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
gdk_win32_window_end_move_resize_drag (window);
case GDK_WINDOW_EDGE_NORTH:
winedge = HTTOP;
break;
case GDK_WINDOW_EDGE_NORTH_EAST:
winedge = HTTOPRIGHT;
break;
case GDK_WINDOW_EDGE_WEST:
winedge = HTLEFT;
break;
case GDK_WINDOW_EDGE_EAST:
winedge = HTRIGHT;
break;
case GDK_WINDOW_EDGE_SOUTH_WEST:
winedge = HTBOTTOMLEFT;
break;
case GDK_WINDOW_EDGE_SOUTH:
winedge = HTBOTTOM;
break;
case GDK_WINDOW_EDGE_SOUTH_EAST:
default:
winedge = HTBOTTOMRIGHT;
break;
}
DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, winedge,
MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
setup_drag_move_resize_context (window, &impl->drag_move_resize_context,
GDK_WIN32_DRAGOP_RESIZE, edge, device,
button, root_x, root_y, timestamp);
}
static void
gdk_win32_window_begin_move_drag (GdkWindow *window,
GdkDevice *device,
gint button,
gint root_x,
gint root_y,
guint32 timestamp)
GdkDevice *device,
gint button,
gint root_x,
gint root_y,
guint32 timestamp)
{
GdkWindowImplWin32 *impl;
g_return_if_fail (GDK_IS_WINDOW (window));
if (GDK_WINDOW_DESTROYED (window))
if (GDK_WINDOW_DESTROYED (window) ||
GDK_WINDOW_TYPE (window) == GDK_WINDOW_CHILD ||
IsIconic (GDK_WINDOW_HWND (window)))
return;
/* Tell Windows to start interactively moving the window by pretending that
@ -2730,13 +2996,14 @@ gdk_win32_window_begin_move_drag (GdkWindow *window,
if (button != 1)
return;
/* Must break the automatic grab that occured when the button was pressed,
* otherwise it won't work.
*/
gdk_device_ungrab (device, 0);
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
DefWindowProcW (GDK_WINDOW_HWND (window), WM_NCLBUTTONDOWN, HTCAPTION,
MAKELPARAM (root_x - _gdk_offset_x, root_y - _gdk_offset_y));
if (impl->drag_move_resize_context.op != GDK_WIN32_DRAGOP_NONE)
gdk_win32_window_end_move_resize_drag (window);
setup_drag_move_resize_context (window, &impl->drag_move_resize_context,
GDK_WIN32_DRAGOP_MOVE, GDK_WINDOW_EDGE_NORTH_WEST,
device, button, root_x, root_y, timestamp);
}
@ -3447,6 +3714,7 @@ gdk_window_impl_win32_class_init (GdkWindowImplWin32Class *klass)
impl_class->destroy_foreign = gdk_win32_window_destroy_foreign;
impl_class->get_shape = gdk_win32_window_get_shape;
//FIXME?: impl_class->get_input_shape = gdk_win32_window_get_input_shape;
impl_class->end_paint = gdk_win32_window_end_paint;
//impl_class->beep = gdk_x11_window_beep;

View File

@ -46,6 +46,53 @@ typedef struct _GdkWindowImplWin32Class GdkWindowImplWin32Class;
#define GDK_IS_WINDOW_IMPL_WIN32_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_WINDOW_IMPL_WIN32))
#define GDK_WINDOW_IMPL_WIN32_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_WINDOW_IMPL_WIN32, GdkWindowImplWin32Class))
enum _GdkW32WindowDragOp
{
GDK_WIN32_DRAGOP_NONE = 0,
GDK_WIN32_DRAGOP_RESIZE,
GDK_WIN32_DRAGOP_MOVE,
GDK_WIN32_DRAGOP_COUNT
};
typedef enum _GdkW32WindowDragOp GdkW32WindowDragOp;
struct _GdkW32DragMoveResizeContext
{
/* The kind of drag-operation going on. */
GdkW32WindowDragOp op;
/* The edge that was grabbed for resizing. Not used for moving. */
GdkWindowEdge edge;
/* Not used */
GdkDevice *device;
/* Not used */
gint button;
/* Initial cursor position when the operation began.
* Current cursor position is subtracted from it to find how far
* to move window border(s).
*/
gint start_root_x;
gint start_root_y;
/* Initial window rectangle (position and size).
* The window is resized/moved relative to this (see start_root_*).
*/
RECT start_rect;
/* Not used */
guint32 timestamp;
/* TRUE if during the next redraw we should call SetWindowPos() to push
* the window size and poistion to the native window.
*/
gboolean native_move_resize_pending;
};
typedef struct _GdkW32DragMoveResizeContext GdkW32DragMoveResizeContext;
struct _GdkWindowImplWin32
{
GdkWindowImpl parent_instance;
@ -83,6 +130,8 @@ struct _GdkWindowImplWin32
HDC hdc;
int hdc_count;
HBITMAP saved_dc_bitmap; /* Original bitmap for dc */
GdkW32DragMoveResizeContext drag_move_resize_context;
};
struct _GdkWindowImplWin32Class