GDK W32: More flexible modal operation mode
Instead of using a boolean to indicate a modal operation being in progress, use a set of flags, and allow these to be set and unset independently. Specifically, this allows WM_CAPTURECHANGED handler to only act when a drag-move or drag-resize modal operation is in progress, and ignore DND (which can also cause WM_CAPTURECHANGED to be posted). This avoids a crash due to assertion failure when OLE2 DND code tries to end a modal operation that was already ended by the WM_CAPTURECHANGED handler. https://bugzilla.gnome.org/show_bug.cgi?id=786121
This commit is contained in:
@@ -1041,7 +1041,7 @@ G_GNUC_END_IGNORE_DEPRECATIONS;
|
|||||||
/* Don't produce any button or motion events while a window is being
|
/* Don't produce any button or motion events while a window is being
|
||||||
* moved or resized, see bug #151090.
|
* moved or resized, see bug #151090.
|
||||||
*/
|
*/
|
||||||
if (_modal_operation_in_progress)
|
if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
|
||||||
{
|
{
|
||||||
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
|
GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n"));
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|||||||
@@ -1896,11 +1896,11 @@ _gdk_win32_dnd_do_dragdrop (void)
|
|||||||
|
|
||||||
GDK_NOTE (DND, g_print ("Calling DoDragDrop\n"));
|
GDK_NOTE (DND, g_print ("Calling DoDragDrop\n"));
|
||||||
|
|
||||||
_gdk_win32_begin_modal_call ();
|
_gdk_win32_begin_modal_call (GDK_WIN32_MODAL_OP_DND);
|
||||||
hr = DoDragDrop (&dobj->ido, &pending_src_context->ids,
|
hr = DoDragDrop (&dobj->ido, &pending_src_context->ids,
|
||||||
DROPEFFECT_COPY | DROPEFFECT_MOVE,
|
DROPEFFECT_COPY | DROPEFFECT_MOVE,
|
||||||
&dwEffect);
|
&dwEffect);
|
||||||
_gdk_win32_end_modal_call ();
|
_gdk_win32_end_modal_call (GDK_WIN32_MODAL_OP_DND);
|
||||||
|
|
||||||
GDK_NOTE (DND, g_print ("DoDragDrop returned %s\n",
|
GDK_NOTE (DND, g_print ("DoDragDrop returned %s\n",
|
||||||
(hr == DRAGDROP_S_DROP ? "DRAGDROP_S_DROP" :
|
(hr == DRAGDROP_S_DROP ? "DRAGDROP_S_DROP" :
|
||||||
|
|||||||
@@ -1736,36 +1736,42 @@ modal_timer_proc (HWND hwnd,
|
|||||||
{
|
{
|
||||||
int arbitrary_limit = 10;
|
int arbitrary_limit = 10;
|
||||||
|
|
||||||
while (_modal_operation_in_progress &&
|
while (_modal_operation_in_progress != GDK_WIN32_MODAL_OP_NONE &&
|
||||||
g_main_context_pending (NULL) &&
|
g_main_context_pending (NULL) &&
|
||||||
arbitrary_limit--)
|
arbitrary_limit--)
|
||||||
g_main_context_iteration (NULL, FALSE);
|
g_main_context_iteration (NULL, FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gdk_win32_begin_modal_call (void)
|
_gdk_win32_begin_modal_call (GdkWin32ModalOpKind kind)
|
||||||
{
|
{
|
||||||
g_assert (!_modal_operation_in_progress);
|
GdkWin32ModalOpKind was = _modal_operation_in_progress;
|
||||||
|
g_assert (!(_modal_operation_in_progress & kind));
|
||||||
|
|
||||||
_modal_operation_in_progress = TRUE;
|
_modal_operation_in_progress |= kind;
|
||||||
|
|
||||||
modal_timer = SetTimer (NULL, 0, 10, modal_timer_proc);
|
if (was == GDK_WIN32_MODAL_OP_NONE)
|
||||||
if (modal_timer == 0)
|
{
|
||||||
WIN32_API_FAILED ("SetTimer");
|
modal_timer = SetTimer (NULL, 0, 10, modal_timer_proc);
|
||||||
|
|
||||||
|
if (modal_timer == 0)
|
||||||
|
WIN32_API_FAILED ("SetTimer");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
_gdk_win32_end_modal_call (void)
|
_gdk_win32_end_modal_call (GdkWin32ModalOpKind kind)
|
||||||
{
|
{
|
||||||
g_assert (_modal_operation_in_progress);
|
g_assert (_modal_operation_in_progress & kind);
|
||||||
|
|
||||||
_modal_operation_in_progress = FALSE;
|
_modal_operation_in_progress &= ~kind;
|
||||||
|
|
||||||
if (modal_timer != 0)
|
if (_modal_operation_in_progress == GDK_WIN32_MODAL_OP_NONE &&
|
||||||
|
modal_timer != 0)
|
||||||
{
|
{
|
||||||
API_CALL (KillTimer, (NULL, modal_timer));
|
API_CALL (KillTimer, (NULL, modal_timer));
|
||||||
modal_timer = 0;
|
modal_timer = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static VOID CALLBACK
|
static VOID CALLBACK
|
||||||
@@ -3246,30 +3252,37 @@ gdk_event_translate (MSG *msg,
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_ENTERSIZEMOVE:
|
case WM_ENTERSIZEMOVE:
|
||||||
case WM_ENTERMENULOOP:
|
_modal_move_resize_window = msg->hwnd;
|
||||||
if (msg->message == WM_ENTERSIZEMOVE)
|
_gdk_win32_begin_modal_call (GDK_WIN32_MODAL_OP_SIZEMOVE_MASK);
|
||||||
_modal_move_resize_window = msg->hwnd;
|
|
||||||
|
|
||||||
_gdk_win32_begin_modal_call ();
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WM_EXITSIZEMOVE:
|
case WM_EXITSIZEMOVE:
|
||||||
case WM_EXITMENULOOP:
|
if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
|
||||||
if (_modal_operation_in_progress)
|
|
||||||
{
|
{
|
||||||
_modal_move_resize_window = NULL;
|
_modal_move_resize_window = NULL;
|
||||||
_gdk_win32_end_modal_call ();
|
_gdk_win32_end_modal_call (GDK_WIN32_MODAL_OP_SIZEMOVE_MASK);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case WM_ENTERMENULOOP:
|
||||||
|
_gdk_win32_begin_modal_call (GDK_WIN32_MODAL_OP_MENU);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case WM_EXITMENULOOP:
|
||||||
|
if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_MENU)
|
||||||
|
_gdk_win32_end_modal_call (GDK_WIN32_MODAL_OP_MENU);
|
||||||
|
break;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case WM_CAPTURECHANGED:
|
case WM_CAPTURECHANGED:
|
||||||
/* Sometimes we don't get WM_EXITSIZEMOVE, for instance when you
|
/* Sometimes we don't get WM_EXITSIZEMOVE, for instance when you
|
||||||
select move/size in the menu and then click somewhere without
|
select move/size in the menu and then click somewhere without
|
||||||
moving/resizing. We work around this using WM_CAPTURECHANGED. */
|
moving/resizing. We work around this using WM_CAPTURECHANGED. */
|
||||||
if (_modal_operation_in_progress)
|
if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
|
||||||
{
|
{
|
||||||
_modal_move_resize_window = NULL;
|
_modal_move_resize_window = NULL;
|
||||||
_gdk_win32_end_modal_call ();
|
_gdk_win32_end_modal_call (GDK_WIN32_MODAL_OP_SIZEMOVE_MASK);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
|
impl = GDK_WINDOW_IMPL_WIN32 (window->impl);
|
||||||
@@ -3425,7 +3438,7 @@ gdk_event_translate (MSG *msg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Call modal timer immediate so that we repaint faster after a resize. */
|
/* Call modal timer immediate so that we repaint faster after a resize. */
|
||||||
if (_modal_operation_in_progress)
|
if (_modal_operation_in_progress & GDK_WIN32_MODAL_OP_SIZEMOVE_MASK)
|
||||||
modal_timer_proc (0,0,0,0);
|
modal_timer_proc (0,0,0,0);
|
||||||
|
|
||||||
/* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */
|
/* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ GdkWin32DndState _dnd_source_state = GDK_WIN32_DND_NONE;
|
|||||||
gint _gdk_input_ignore_wintab = FALSE;
|
gint _gdk_input_ignore_wintab = FALSE;
|
||||||
gint _gdk_max_colors = 0;
|
gint _gdk_max_colors = 0;
|
||||||
|
|
||||||
gboolean _modal_operation_in_progress = FALSE;
|
GdkWin32ModalOpKind _modal_operation_in_progress = GDK_WIN32_MODAL_OP_NONE;
|
||||||
HWND _modal_move_resize_window = NULL;
|
HWND _modal_move_resize_window = NULL;
|
||||||
gboolean _ignore_destroy_clipboard = FALSE;
|
gboolean _ignore_destroy_clipboard = FALSE;
|
||||||
|
|
||||||
|
|||||||
@@ -343,8 +343,23 @@ void _gdk_win32_ole2_dnd_property_change (GdkAtom type,
|
|||||||
const guchar *data,
|
const guchar *data,
|
||||||
gint nelements);
|
gint nelements);
|
||||||
|
|
||||||
void _gdk_win32_begin_modal_call (void);
|
typedef enum {
|
||||||
void _gdk_win32_end_modal_call (void);
|
GDK_WIN32_MODAL_OP_NONE = 0x0,
|
||||||
|
GDK_WIN32_MODAL_OP_SIZE = 0x1 << 0,
|
||||||
|
GDK_WIN32_MODAL_OP_MOVE = 0x1 << 1,
|
||||||
|
GDK_WIN32_MODAL_OP_MENU = 0x1 << 2,
|
||||||
|
GDK_WIN32_MODAL_OP_DND = 0x1 << 3
|
||||||
|
} GdkWin32ModalOpKind;
|
||||||
|
|
||||||
|
#define GDK_WIN32_MODAL_OP_SIZEMOVE_MASK (GDK_WIN32_MODAL_OP_SIZE | GDK_WIN32_MODAL_OP_MOVE)
|
||||||
|
|
||||||
|
/* Non-zero while a modal sizing, moving, or dnd operation is in progress */
|
||||||
|
extern GdkWin32ModalOpKind _modal_operation_in_progress;
|
||||||
|
|
||||||
|
extern HWND _modal_move_resize_window;
|
||||||
|
|
||||||
|
void _gdk_win32_begin_modal_call (GdkWin32ModalOpKind kind);
|
||||||
|
void _gdk_win32_end_modal_call (GdkWin32ModalOpKind kind);
|
||||||
|
|
||||||
|
|
||||||
/* Options */
|
/* Options */
|
||||||
@@ -353,11 +368,6 @@ extern gint _gdk_max_colors;
|
|||||||
|
|
||||||
#define GDK_WIN32_COLORMAP_DATA(cmap) ((GdkColormapPrivateWin32 *) GDK_COLORMAP (cmap)->windowing_data)
|
#define GDK_WIN32_COLORMAP_DATA(cmap) ((GdkColormapPrivateWin32 *) GDK_COLORMAP (cmap)->windowing_data)
|
||||||
|
|
||||||
/* TRUE while a modal sizing, moving, or dnd operation is in progress */
|
|
||||||
extern gboolean _modal_operation_in_progress;
|
|
||||||
|
|
||||||
extern HWND _modal_move_resize_window;
|
|
||||||
|
|
||||||
/* TRUE when we are emptying the clipboard ourselves */
|
/* TRUE when we are emptying the clipboard ourselves */
|
||||||
extern gboolean _ignore_destroy_clipboard;
|
extern gboolean _ignore_destroy_clipboard;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user