diff --git a/build/win32/vs10/gtk+.props b/build/win32/vs10/gtk+.props index 3ec8cc2e0a..b9b41ffc98 100644 --- a/build/win32/vs10/gtk+.props +++ b/build/win32/vs10/gtk+.props @@ -569,7 +569,7 @@ copy $(Configuration)\$(Platform)\bin\*-$(GtkApiVersion).lib $(CopyDir)\lib ..\..\..;$(GlibEtcInstallRoot)\lib\glib-2.0\include;$(GlibEtcInstallRoot)\include\glib-2.0;$(GlibEtcInstallRoot)\include;$(GlibEtcInstallRoot)\include\cairo;$(GlibEtcInstallRoot)\include\atk-1.0;$(GlibEtcInstallRoot)\include\pango-1.0;$(GlibEtcInstallRoot)\include\GdkPixbuf-2.0;%(AdditionalIncludeDirectories) - HAVE_CONFIG_H;G_DISABLE_DEPRECATED;G_DISABLE_SINGLE_INCLUDES;ATK_DISABLE_SINGLE_INCLUDES;GDK_PIXBUF_DISABLE_SINGLE_INCLUDES;GTK_DISABLE_SINGLE_INCLUDES;%(PreprocessorDefinitions) + HAVE_CONFIG_H;G_DISABLE_SINGLE_INCLUDES;ATK_DISABLE_SINGLE_INCLUDES;GDK_PIXBUF_DISABLE_SINGLE_INCLUDES;GTK_DISABLE_SINGLE_INCLUDES;%(PreprocessorDefinitions) msvc_recommended_pragmas.h;%(ForcedIncludeFiles) diff --git a/build/win32/vs9/gtk+.vsprops b/build/win32/vs9/gtk+.vsprops index fe614cf2ab..ee0ca8c9f6 100644 --- a/build/win32/vs9/gtk+.vsprops +++ b/build/win32/vs9/gtk+.vsprops @@ -9,7 +9,7 @@ ]]) +fi ################################################################ # Strip -export-dynamic from the link lines of various libraries diff --git a/gdk/gdk.symbols b/gdk/gdk.symbols index 58f3401315..d4f207229a 100644 --- a/gdk/gdk.symbols +++ b/gdk/gdk.symbols @@ -1237,6 +1237,7 @@ gdk_window_destroy_notify #if IN_HEADER(__GDK_WIN32_H__) #if IN_FILE(__GDK_WINDOW_WIN32_C__) gdk_win32_window_is_win32 +gdk_win32_window_get_impl_hwnd gdk_win32_begin_direct_draw_libgtk_only gdk_win32_end_direct_draw_libgtk_only gdk_win32_window_lookup_for_display diff --git a/gdk/gdkinternals.h b/gdk/gdkinternals.h index e861a4ef2c..3234f2ebf0 100644 --- a/gdk/gdkinternals.h +++ b/gdk/gdkinternals.h @@ -672,6 +672,7 @@ gboolean _gdk_window_has_impl (GdkWindow *window); GdkWindow * _gdk_window_get_impl_window (GdkWindow *window); GdkWindow *_gdk_window_get_input_window_for_event (GdkWindow *native_window, GdkEventType event_type, + GdkModifierType mask, int x, int y, gulong serial); GdkRegion *_gdk_region_new_from_yxbanded_rects (GdkRectangle *rects, int n_rects); diff --git a/gdk/gdkwindow.c b/gdk/gdkwindow.c index f05857041c..101e5c16c2 100644 --- a/gdk/gdkwindow.c +++ b/gdk/gdkwindow.c @@ -10745,7 +10745,7 @@ proxy_button_event (GdkEvent *source_event, _gdk_display_add_pointer_grab (display, pointer_window, - toplevel_window, + event_window, FALSE, gdk_window_get_events (pointer_window), serial, @@ -11100,6 +11100,7 @@ static GdkWindow * get_extension_event_window (GdkDisplay *display, GdkWindow *pointer_window, GdkEventType type, + GdkModifierType mask, gulong serial) { guint evmask; @@ -11112,6 +11113,7 @@ get_extension_event_window (GdkDisplay *display, if (grab != NULL && !grab->owner_events) { evmask = grab->event_mask; + evmask = update_evmask_for_button_motion (evmask, mask); grab_window = grab->window; @@ -11125,6 +11127,7 @@ get_extension_event_window (GdkDisplay *display, while (w != NULL) { evmask = w->extension_events; + evmask = update_evmask_for_button_motion (evmask, mask); if (evmask & type_masks[type]) return (GdkWindow *)w; @@ -11136,6 +11139,7 @@ get_extension_event_window (GdkDisplay *display, grab->owner_events) { evmask = grab->event_mask; + evmask = update_evmask_for_button_motion (evmask, mask); if (evmask & type_masks[type]) return grab->window; @@ -11150,6 +11154,7 @@ get_extension_event_window (GdkDisplay *display, GdkWindow * _gdk_window_get_input_window_for_event (GdkWindow *native_window, GdkEventType event_type, + GdkModifierType mask, int x, int y, gulong serial) { @@ -11171,6 +11176,7 @@ _gdk_window_get_input_window_for_event (GdkWindow *native_window, event_win = get_extension_event_window (display, pointer_window, event_type, + mask, serial); return event_win; diff --git a/gdk/win32/gdkdisplay-win32.c b/gdk/win32/gdkdisplay-win32.c index 2611c03015..cef60721a1 100644 --- a/gdk/win32/gdkdisplay-win32.c +++ b/gdk/win32/gdkdisplay-win32.c @@ -370,7 +370,9 @@ inner_clipboard_window_procedure (HWND hwnd, { int success; HWND hwndOwner; +#ifdef G_ENABLE_DEBUG UINT nFormat = 0; +#endif GdkEvent *event; GdkWindow *owner; diff --git a/gdk/win32/gdkdrawable-win32.c b/gdk/win32/gdkdrawable-win32.c index 8e09be73e9..622200d33d 100644 --- a/gdk/win32/gdkdrawable-win32.c +++ b/gdk/win32/gdkdrawable-win32.c @@ -1540,20 +1540,50 @@ blit_from_pixmap (gboolean use_fg_bg, } static void -blit_inside_drawable (HDC hdc, - GdkGCWin32 *gcwin32, - gint xsrc, - gint ysrc, - gint xdest, - gint ydest, - gint width, - gint height) +blit_inside_drawable (HDC hdc, + GdkGCWin32 *gcwin32, + GdkDrawableImplWin32 *src, + gint xsrc, + gint ysrc, + gint xdest, + gint ydest, + gint width, + gint height) { GDK_NOTE (DRAW, g_print ("blit_inside_drawable\n")); - GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height, - hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2))); + if GDK_IS_WINDOW_IMPL_WIN32 (src) + { + /* Simply calling BitBlt() instead of these ScrollDC() gymnastics might + * seem tempting, but we need to do this to prevent blitting garbage when + * scrolling a window that is partially obscured by another window. For + * example, GIMP's toolbox being over the editor window. */ + + RECT scrollRect, emptyRect; + HRGN updateRgn; + + scrollRect.left = MIN (xsrc, xdest); + scrollRect.top = MIN (ysrc, ydest); + scrollRect.right = MAX (xsrc + width + 1, xdest + width + 1); + scrollRect.bottom = MAX (ysrc + height + 1, ydest + height + 1); + + SetRectEmpty (&emptyRect); + updateRgn = CreateRectRgnIndirect (&emptyRect); + + if (!ScrollDC (hdc, xdest - xsrc, ydest - ysrc, &scrollRect, NULL, updateRgn, NULL)) + WIN32_GDI_FAILED ("ScrollDC"); + else if (!InvalidateRgn (src->handle, updateRgn, FALSE)) + WIN32_GDI_FAILED ("InvalidateRgn"); + + if (!DeleteObject (updateRgn)) + WIN32_GDI_FAILED ("DeleteObject"); + } + else + { + GDI_CALL (BitBlt, (hdc, xdest, ydest, width, height, + hdc, xsrc, ysrc, rop2_to_rop3 (gcwin32->rop2))); + } } static void @@ -1743,13 +1773,15 @@ _gdk_win32_blit (gboolean use_fg_bg, } if (draw_impl->handle == src_impl->handle) - blit_inside_drawable (hdc, GDK_GC_WIN32 (gc), xsrc, ysrc, xdest, ydest, width, height); + blit_inside_drawable (hdc, GDK_GC_WIN32 (gc), src_impl, + xsrc, ysrc, xdest, ydest, width, height); else if (GDK_IS_PIXMAP_IMPL_WIN32 (src_impl)) blit_from_pixmap (use_fg_bg, draw_impl, hdc, (GdkPixmapImplWin32 *) src_impl, gc, xsrc, ysrc, xdest, ydest, width, height); else - blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, xsrc, ysrc, xdest, ydest, width, height); + blit_from_window (hdc, GDK_GC_WIN32 (gc), src_impl, + xsrc, ysrc, xdest, ydest, width, height); gdk_win32_hdc_release (&draw_impl->parent_instance, gc, GDK_GC_FOREGROUND); } diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index 8dec80c167..1cde4fc40c 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -76,10 +76,16 @@ #define MK_XBUTTON2 64 #endif +/* Undefined flags: */ +#define SWP_NOCLIENTSIZE 0x0800 +#define SWP_NOCLIENTMOVE 0x1000 +#define SWP_STATECHANGED 0x8000 /* * Private function declarations */ +#define SYNAPSIS_ICON_WINDOW_CLASS "SynTrackCursorWindowClass" + static gboolean gdk_event_translate (MSG *msg, gint *ret_valp); static void handle_wm_paint (MSG *msg, @@ -94,8 +100,6 @@ static gboolean gdk_event_dispatch (GSource *source, GSourceFunc callback, gpointer user_data); -static gboolean is_modally_blocked (GdkWindow *window); - /* Private variable declarations */ @@ -112,7 +116,8 @@ static GSourceFuncs event_funcs = { GPollFD event_poll_fd; -static GdkWindow *current_toplevel = NULL; +static GdkWindow *mouse_window = NULL; +static GdkWindow *mouse_window_ignored_leave = NULL; static gint current_x, current_y; static gint current_root_x, current_root_y; static UINT client_message; @@ -130,13 +135,6 @@ static UINT sync_timer = 0; static int debug_indent = 0; -static void -synthesize_enter_or_leave_event (GdkWindow *window, - MSG *msg, - GdkEventType type, - GdkCrossingMode mode, - GdkNotifyType detail); - static void assign_object (gpointer lhsp, gpointer rhs) @@ -382,10 +380,9 @@ _gdk_events_init (void) gboolean gdk_events_pending (void) { - MSG msg; return (_gdk_event_queue_find_first (_gdk_display) || (modal_win32_dialog == NULL && - PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE))); + GetQueueStatus (QS_ALLINPUT) != 0)); } GdkEvent* @@ -521,6 +518,9 @@ gdk_display_pointer_ungrab (GdkDisplay *display, info->serial_end = 0; ReleaseCapture (); } + + _gdk_input_ungrab_pointer (time); + /* TODO_CSW: cursor, confines, etc */ _gdk_display_pointer_grab_update (display, 0); @@ -531,45 +531,44 @@ static GdkWindow * find_window_for_mouse_event (GdkWindow* reported_window, MSG* msg) { - HWND hwnd; - POINTS points; POINT pt; - GdkWindow* other_window = NULL; + GdkWindow *event_window; + HWND hwnd; + RECT rect; + GdkPointerGrabInfo *grab; - if (!_gdk_display_get_last_pointer_grab (_gdk_display)) + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab == NULL) return reported_window; - points = MAKEPOINTS (msg->lParam); - pt.x = points.x; - pt.y = points.y; - ClientToScreen (msg->hwnd, &pt); + pt = msg->pt; - hwnd = WindowFromPoint (pt); - - if (hwnd != NULL) + if (!grab->owner_events) + event_window = grab->native_window; + else { - RECT rect; + event_window = NULL; + hwnd = WindowFromPoint (pt); + if (hwnd != NULL) + { + POINT client_pt = pt; - GetClientRect (hwnd, &rect); - ScreenToClient (hwnd, &pt); - if (!PtInRect (&rect, pt)) - return _gdk_root; - - other_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); + ScreenToClient (hwnd, &client_pt); + GetClientRect (hwnd, &rect); + if (PtInRect (&rect, client_pt)) + event_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); + } + if (event_window == NULL) + event_window = grab->native_window; } - if (other_window == NULL) - return _gdk_root; - /* need to also adjust the coordinates to the new window */ - pt.x = points.x; - pt.y = points.y; - ClientToScreen (msg->hwnd, &pt); - ScreenToClient (GDK_WINDOW_HWND (other_window), &pt); + ScreenToClient (GDK_WINDOW_HWND (event_window), &pt); + /* ATTENTION: need to update client coords */ msg->lParam = MAKELPARAM (pt.x, pt.y); - return other_window; + return event_window; } GdkGrabStatus @@ -1205,36 +1204,226 @@ do_show_window (GdkWindow *window, gboolean hide_window) } static void -synthesize_enter_or_leave_event (GdkWindow *window, - MSG *msg, - GdkEventType type, - GdkCrossingMode mode, - GdkNotifyType detail) +send_crossing_event (GdkDisplay *display, + GdkWindowObject *window, + GdkEventType type, + GdkCrossingMode mode, + GdkNotifyType notify_type, + GdkWindow *subwindow, + POINT *screen_pt, + GdkModifierType mask, + guint32 time_) { GdkEvent *event; + GdkPointerGrabInfo *grab; POINT pt; - pt = msg->pt; + grab = _gdk_display_has_pointer_grab (display, 0); + + if (grab != NULL && + !grab->owner_events && + mode != GDK_CROSSING_UNGRAB) + { + /* !owner_event => only report events wrt grab window, ignore rest */ + if ((GdkWindow *)window != grab->native_window) + return; + } + + pt = *screen_pt; ScreenToClient (GDK_WINDOW_HWND (window), &pt); event = gdk_event_new (type); - event->crossing.window = window; - event->crossing.subwindow = NULL; - event->crossing.time = _gdk_win32_get_next_tick (msg->time); + event->crossing.window = (GdkWindow *)window; + event->crossing.subwindow = subwindow; + event->crossing.time = _gdk_win32_get_next_tick (time_); event->crossing.x = pt.x; event->crossing.y = pt.y; - event->crossing.x_root = msg->pt.x + _gdk_offset_x; - event->crossing.y_root = msg->pt.y + _gdk_offset_y; + event->crossing.x_root = screen_pt->x + _gdk_offset_x; + event->crossing.y_root = screen_pt->y + _gdk_offset_y; event->crossing.mode = mode; - event->crossing.detail = detail; - event->crossing.focus = TRUE; /* FIXME: Set correctly */ - event->crossing.state = 0; /* FIXME: Set correctly */ + event->crossing.detail = notify_type; + event->crossing.mode = mode; + event->crossing.detail = notify_type; + event->crossing.focus = FALSE; + event->crossing.state = mask; _gdk_win32_append_event (event); - if (type == GDK_ENTER_NOTIFY && - ((GdkWindowObject *) window)->extension_events != 0) - _gdk_input_enter_event (window); + /* + if (((GdkWindowObject *) window)->extension_events != 0) + _gdk_input_crossing_event ((GdkWindow *)window, type == GDK_ENTER_NOTIFY); + */ +} + +static GdkWindowObject * +get_native_parent (GdkWindowObject *window) +{ + if (window->parent != NULL) + return window->parent->impl_window; + return NULL; +} + + +static GdkWindowObject * +find_common_ancestor (GdkWindowObject *win1, + GdkWindowObject *win2) +{ + GdkWindowObject *tmp; + GList *path1 = NULL, *path2 = NULL; + GList *list1, *list2; + + tmp = win1; + while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT) + { + path1 = g_list_prepend (path1, tmp); + tmp = get_native_parent (tmp); + } + + tmp = win2; + while (tmp != NULL && tmp->window_type != GDK_WINDOW_ROOT) + { + path2 = g_list_prepend (path2, tmp); + tmp = get_native_parent (tmp); + } + + list1 = path1; + list2 = path2; + tmp = NULL; + while (list1 && list2 && (list1->data == list2->data)) + { + tmp = (GdkWindowObject *)list1->data; + list1 = g_list_next (list1); + list2 = g_list_next (list2); + } + g_list_free (path1); + g_list_free (path2); + + return tmp; +} + +void +synthesize_crossing_events (GdkDisplay *display, + GdkWindow *src, + GdkWindow *dest, + GdkCrossingMode mode, + POINT *screen_pt, + GdkModifierType mask, + guint32 time_, + gboolean non_linear) +{ + GdkWindowObject *c; + GdkWindowObject *win, *last, *next; + GList *path, *list; + GdkWindowObject *a; + GdkWindowObject *b; + GdkNotifyType notify_type; + + a = (GdkWindowObject *)src; + b = (GdkWindowObject *)dest; + if (a == b) + return; /* No crossings generated between src and dest */ + + c = find_common_ancestor (a, b); + + non_linear |= (c != a) && (c != b); + + if (a) /* There might not be a source (i.e. if no previous pointer_in_window) */ + { + /* Traverse up from a to (excluding) c sending leave events */ + if (non_linear) + notify_type = GDK_NOTIFY_NONLINEAR; + else if (c == a) + notify_type = GDK_NOTIFY_INFERIOR; + else + notify_type = GDK_NOTIFY_ANCESTOR; + send_crossing_event (display, + a, GDK_LEAVE_NOTIFY, + mode, + notify_type, + NULL, + screen_pt, + mask, time_); + + if (c != a) + { + if (non_linear) + notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL; + else + notify_type = GDK_NOTIFY_VIRTUAL; + + last = a; + win = get_native_parent (a); + while (win != c && win->window_type != GDK_WINDOW_ROOT) + { + send_crossing_event (display, + win, GDK_LEAVE_NOTIFY, + mode, + notify_type, + (GdkWindow *)last, + screen_pt, + mask, time_); + + last = win; + win = get_native_parent (win); + } + } + } + + if (b) /* Might not be a dest, e.g. if we're moving out of the window */ + { + /* Traverse down from c to b */ + if (c != b) + { + path = NULL; + win = get_native_parent (b); + while (win != c && win->window_type != GDK_WINDOW_ROOT) + { + path = g_list_prepend (path, win); + win = get_native_parent (win); + } + + if (non_linear) + notify_type = GDK_NOTIFY_NONLINEAR_VIRTUAL; + else + notify_type = GDK_NOTIFY_VIRTUAL; + + list = path; + while (list) + { + win = (GdkWindowObject *)list->data; + list = g_list_next (list); + if (list) + next = (GdkWindowObject *)list->data; + else + next = b; + + send_crossing_event (display, + win, GDK_ENTER_NOTIFY, + mode, + notify_type, + (GdkWindow *)next, + screen_pt, + mask, time_); + } + g_list_free (path); + } + + + if (non_linear) + notify_type = GDK_NOTIFY_NONLINEAR; + else if (c == a) + notify_type = GDK_NOTIFY_ANCESTOR; + else + notify_type = GDK_NOTIFY_INFERIOR; + + send_crossing_event (display, + b, GDK_ENTER_NOTIFY, + mode, + notify_type, + NULL, + screen_pt, + mask, time_); + } } static void @@ -1344,8 +1533,7 @@ propagate (GdkWindow **window, gboolean grab_owner_events, gint grab_mask, gboolean (*doesnt_want_it) (gint mask, - MSG *msg), - gboolean check_extended) + MSG *msg)) { if (grab_window != NULL && !grab_owner_events) { @@ -1354,13 +1542,6 @@ propagate (GdkWindow **window, /* See if the event should be ignored because an extended input * device is used */ - if (check_extended && - ((GdkWindowObject *) grab_window)->extension_events != 0 && - _gdk_input_ignore_core) - { - GDK_NOTE (EVENTS, g_print (" (ignored for grabber)")); - return FALSE; - } if ((*doesnt_want_it) (grab_mask, msg)) { GDK_NOTE (EVENTS, g_print (" (grabber doesn't want it)")); @@ -1379,13 +1560,6 @@ propagate (GdkWindow **window, */ while (TRUE) { - if (check_extended && - ((GdkWindowObject *) *window)->extension_events != 0 && - _gdk_input_ignore_core) - { - GDK_NOTE (EVENTS, g_print (" (ignored)")); - return FALSE; - } if ((*doesnt_want_it) (((GdkWindowObject *) *window)->event_mask, msg)) { /* Owner doesn't want it, propagate to parent. */ @@ -1397,13 +1571,6 @@ propagate (GdkWindow **window, { /* Event source is grabbed with owner_events TRUE */ - if (check_extended && - ((GdkWindowObject *) grab_window)->extension_events != 0 && - _gdk_input_ignore_core) - { - GDK_NOTE (EVENTS, g_print (" (ignored for grabber)")); - return FALSE; - } if ((*doesnt_want_it) (grab_mask, msg)) { /* Grabber doesn't want it either */ @@ -1452,28 +1619,35 @@ doesnt_want_char (gint mask, return !(mask & (GDK_KEY_PRESS_MASK | GDK_KEY_RELEASE_MASK)); } -static void -handle_configure_event (MSG *msg, - GdkWindow *window) +void +_gdk_win32_emit_configure_event (GdkWindow *window) { + GdkWindowImplWin32 *window_impl; RECT client_rect; POINT point; GdkWindowObject *window_object; + HWND hwnd; - GetClientRect (msg->hwnd, &client_rect); + window_object = GDK_WINDOW_OBJECT (window); + + window_impl = GDK_WINDOW_IMPL_WIN32 (window_object->impl); + if (window_impl->inhibit_configure) + return; + + hwnd = GDK_WINDOW_HWND (window); + + GetClientRect (hwnd, &client_rect); point.x = client_rect.left; /* always 0 */ point.y = client_rect.top; /* top level windows need screen coords */ if (gdk_window_get_parent (window) == _gdk_root) { - ClientToScreen (msg->hwnd, &point); + ClientToScreen (hwnd, &point); point.x += _gdk_offset_x; point.y += _gdk_offset_y; } - window_object = GDK_WINDOW_OBJECT (window); - window_object->width = client_rect.right - client_rect.left; window_object->height = client_rect.bottom - client_rect.top; @@ -1634,7 +1808,7 @@ modal_timer_proc (HWND hwnd, UINT_PTR id, DWORD time) { - int arbitrary_limit = 1; + int arbitrary_limit = 10; while (_modal_operation_in_progress && g_main_context_pending (NULL) && @@ -1855,6 +2029,12 @@ ensure_stacking_on_activate_app (MSG *msg, } } +#define GDK_ANY_BUTTON_MASK (GDK_BUTTON1_MASK | \ + GDK_BUTTON2_MASK | \ + GDK_BUTTON3_MASK | \ + GDK_BUTTON4_MASK | \ + GDK_BUTTON5_MASK) + static gboolean gdk_event_translate (MSG *msg, gint *ret_valp) @@ -1867,6 +2047,7 @@ gdk_event_translate (MSG *msg, BYTE key_state[256]; HIMC himc; WINDOWPOS *windowpos; + gboolean ignore_leave; GdkEvent *event; @@ -1876,7 +2057,7 @@ gdk_event_translate (MSG *msg, GdkWindow *window = NULL; GdkWindowImplWin32 *impl; - GdkWindow *orig_window, *new_window, *toplevel; + GdkWindow *orig_window, *new_window; GdkPointerGrabInfo *grab = NULL; GdkWindow *grab_window = NULL; @@ -1915,19 +2096,6 @@ gdk_event_translate (MSG *msg, GDK_NOTE (EVENTS, g_print (" %d", (int) msg->wParam)); exit (msg->wParam); } - else if (msg->message == WM_MOVE || - msg->message == WM_SIZE) - { - /* It's quite normal to get these messages before we have - * had time to register the window in our lookup table, or - * when the window is being destroyed and we already have - * removed it. Repost the same message to our queue so that - * we will get it later when we are prepared. - */ - GDK_NOTE (EVENTS, g_print (" (posted)")); - - PostMessageW (msg->hwnd, msg->message, msg->wParam, msg->lParam); - } else if (msg->message == WM_CREATE) { window = (UNALIGNED GdkWindow*) (((LPCREATESTRUCTW) msg->lParam)->lpCreateParams); @@ -2085,7 +2253,7 @@ gdk_event_translate (MSG *msg, _gdk_display->keyboard_grab.window, _gdk_display->keyboard_grab.owner_events, GDK_ALL_EVENTS_MASK, - doesnt_want_key, FALSE)) + doesnt_want_key)) break; if (GDK_WINDOW_DESTROYED (window)) @@ -2193,7 +2361,7 @@ gdk_event_translate (MSG *msg, _gdk_display->keyboard_grab.window, _gdk_display->keyboard_grab.owner_events, GDK_ALL_EVENTS_MASK, - doesnt_want_char, FALSE)) + doesnt_want_char)) break; if (GDK_WINDOW_DESTROYED (window)) @@ -2257,11 +2425,16 @@ gdk_event_translate (MSG *msg, GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam))); assign_object (&window, find_window_for_mouse_event (window, msg)); - /* TODO_CSW?: there used to some synthesize and propagate */ + if (GDK_WINDOW_DESTROYED (window)) break; - /* TODO_CSW? Emulate X11's automatic active grab */ + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab == NULL) + { + SetCapture (GDK_WINDOW_HWND (window)); + } + generate_button_event (GDK_BUTTON_PRESS, button, window, msg); @@ -2292,14 +2465,38 @@ gdk_event_translate (MSG *msg, GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam))); assign_object (&window, find_window_for_mouse_event (window, msg)); -#if 0 - if (((GdkWindowObject *) window)->extension_events != 0 && - _gdk_input_ignore_core) + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab != NULL && grab->implicit) { - GDK_NOTE (EVENTS, g_print (" (ignored)")); - break; + gint state = build_pointer_event_state (msg); + + /* We keep the implicit grab until no buttons at all are held down */ + if ((state & GDK_ANY_BUTTON_MASK & ~(GDK_BUTTON1_MASK << (button - 1))) == 0) + { + ReleaseCapture (); + + new_window = NULL; + hwnd = WindowFromPoint (msg->pt); + if (hwnd != NULL) + { + POINT client_pt = msg->pt; + + ScreenToClient (hwnd, &client_pt); + GetClientRect (hwnd, &rect); + if (PtInRect (&rect, client_pt)) + new_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); + } + synthesize_crossing_events (_gdk_display, + grab->native_window, new_window, + GDK_CROSSING_UNGRAB, + &msg->pt, + 0, /* TODO: Set right mask */ + msg->time, + FALSE); + assign_object (&mouse_window, new_window); + mouse_window_ignored_leave = NULL; + } } -#endif generate_button_event (GDK_BUTTON_RELEASE, button, window, msg); @@ -2313,22 +2510,61 @@ gdk_event_translate (MSG *msg, (gpointer) msg->wParam, GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam))); - assign_object (&window, find_window_for_mouse_event (window, msg)); - toplevel = gdk_window_get_toplevel (window); - if (current_toplevel != toplevel) + new_window = window; + + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab != NULL) { - GDK_NOTE (EVENTS, g_print (" toplevel %p -> %p", - current_toplevel ? GDK_WINDOW_HWND (current_toplevel) : NULL, - toplevel ? GDK_WINDOW_HWND (toplevel) : NULL)); - if (current_toplevel) - synthesize_enter_or_leave_event (current_toplevel, msg, - GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); - synthesize_enter_or_leave_event (toplevel, msg, - GDK_ENTER_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); - assign_object (¤t_toplevel, toplevel); - track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (toplevel)); + POINT pt; + pt = msg->pt; + + new_window = NULL; + hwnd = WindowFromPoint (pt); + if (hwnd != NULL) + { + POINT client_pt = pt; + + ScreenToClient (hwnd, &client_pt); + GetClientRect (hwnd, &rect); + if (PtInRect (&rect, client_pt)) + new_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); + } + + if (!grab->owner_events && + new_window != NULL && + new_window != grab->native_window) + new_window = NULL; } + if (mouse_window != new_window) + { + GDK_NOTE (EVENTS, g_print (" mouse_sinwod %p -> %p", + mouse_window ? GDK_WINDOW_HWND (mouse_window) : NULL, + new_window ? GDK_WINDOW_HWND (new_window) : NULL)); + synthesize_crossing_events (_gdk_display, + mouse_window, new_window, + GDK_CROSSING_NORMAL, + &msg->pt, + 0, /* TODO: Set right mask */ + msg->time, + FALSE); + assign_object (&mouse_window, new_window); + mouse_window_ignored_leave = NULL; + if (new_window != NULL) + track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (new_window)); + } + else if (new_window != NULL && + new_window == mouse_window_ignored_leave) + { + /* If we ignored a leave event for this window and we're now getting + input again we need to re-arm the mouse tracking, as that was + cancelled by the mouseleave. */ + mouse_window_ignored_leave = NULL; + track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (new_window)); + } + + assign_object (&window, find_window_for_mouse_event (window, msg)); + /* If we haven't moved, don't create any GDK event. Windows * sends WM_MOUSEMOVE messages after a new window is shows under * the mouse, even if the mouse hasn't moved. This disturbs gtk. @@ -2367,22 +2603,41 @@ gdk_event_translate (MSG *msg, GDK_NOTE (EVENTS, g_print (" %d (%ld,%ld)", HIWORD (msg->wParam), msg->pt.x, msg->pt.y)); - if (!gdk_win32_handle_table_lookup ((GdkNativeWindow) WindowFromPoint (msg->pt))) + new_window = NULL; + hwnd = WindowFromPoint (msg->pt); + ignore_leave = FALSE; + if (hwnd != NULL) { - /* we are only interested if we don't know the new window */ - if (current_toplevel) - synthesize_enter_or_leave_event (current_toplevel, msg, - GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); - assign_object (¤t_toplevel, NULL); - } - else if (window != gdk_window_get_toplevel (window)) /* xxx: only for native child windows? */ - { - /* XXX: this used to be ignored pre-csw, but I think we need at least some - * of the leave events */ - synthesize_enter_or_leave_event (window, msg, - GDK_LEAVE_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); + char classname[64]; + + POINT client_pt = msg->pt; + + /* The synapitics trackpad drivers have this irritating + feature where it pops up a window right under the pointer + when you scroll. We ignore the leave and enter events for + this window */ + if (GetClassNameA (hwnd, classname, sizeof(classname)) && + strcmp (classname, SYNAPSIS_ICON_WINDOW_CLASS) == 0) + ignore_leave = TRUE; + + ScreenToClient (hwnd, &client_pt); + GetClientRect (hwnd, &rect); + if (PtInRect (&rect, client_pt)) + new_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); } + if (!ignore_leave) + synthesize_crossing_events (_gdk_display, + mouse_window, new_window, + GDK_CROSSING_NORMAL, + &msg->pt, + 0, /* TODO: Set right mask */ + msg->time, + FALSE); + assign_object (&mouse_window, new_window); + mouse_window_ignored_leave = ignore_leave ? new_window : NULL; + + return_val = TRUE; break; @@ -2399,6 +2654,30 @@ gdk_event_translate (MSG *msg, if ((hwnd = WindowFromPoint (point)) == NULL) break; + + { + char classname[64]; + + /* The synapitics trackpad drivers have this irritating + feature where it pops up a window right under the pointer + when you scroll. We backtrack and to the toplevel and + find the innermost child instead. */ + if (GetClassNameA (hwnd, classname, sizeof(classname)) && + strcmp (classname, SYNAPSIS_ICON_WINDOW_CLASS) == 0) + { + HWND hwndc; + + /* Find our toplevel window */ + hwnd = GetAncestor (msg->hwnd, GA_ROOT); + + /* Walk back up to the outermost child at the desired point */ + do { + ScreenToClient (hwnd, &point); + hwndc = ChildWindowFromPoint (hwnd, point); + ClientToScreen (hwnd, &point); + } while (hwndc != hwnd && (hwnd = hwndc, 1)); + } + } msg->hwnd = hwnd; if ((new_window = gdk_win32_handle_table_lookup ((GdkNativeWindow) msg->hwnd)) == NULL) @@ -2497,8 +2776,6 @@ gdk_event_translate (MSG *msg, case WM_MOUSEACTIVATE: { - GdkWindow *tmp; - if (gdk_window_get_window_type (window) == GDK_WINDOW_TEMP || !((GdkWindowObject *)window)->accept_focus) { @@ -2506,15 +2783,10 @@ gdk_event_translate (MSG *msg, return_val = TRUE; } - tmp = _gdk_modal_current (); - - if (tmp != NULL) + if (_gdk_modal_blocked (gdk_window_get_toplevel (window))) { - if (gdk_window_get_toplevel (window) != tmp) - { - *ret_valp = MA_NOACTIVATEANDEAT; - return_val = TRUE; - } + *ret_valp = MA_NOACTIVATEANDEAT; + return_val = TRUE; } } @@ -2572,14 +2844,6 @@ gdk_event_translate (MSG *msg, { grab_window = grab->window; } - else if (window != gdk_window_get_toplevel (window)) /* xxx: only for native child windows? */ - { - /* when entering a new window we are Windows is always asking for a new cursor - * so this might be a good spot to emmulate enter-notify events */ - synthesize_enter_or_leave_event (window, msg, - GDK_ENTER_NOTIFY, GDK_CROSSING_NORMAL, GDK_NOTIFY_ANCESTOR); - track_mouse_event (TME_LEAVE, GDK_WINDOW_HWND (window)); - } if (grab_window == NULL && LOWORD (msg->lParam) != HTCLIENT) break; @@ -2600,54 +2864,6 @@ gdk_event_translate (MSG *msg, } break; - case WM_SHOWWINDOW: - GDK_NOTE (EVENTS, g_print (" %s %s", - (msg->wParam ? "YES" : "NO"), - (msg->lParam == 0 ? "ShowWindow" : - (msg->lParam == SW_OTHERUNZOOM ? "OTHERUNZOOM" : - (msg->lParam == SW_OTHERZOOM ? "OTHERZOOM" : - (msg->lParam == SW_PARENTCLOSING ? "PARENTCLOSING" : - (msg->lParam == SW_PARENTOPENING ? "PARENTOPENING" : - "???"))))))); - - if (!(((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK)) - break; - - if (msg->lParam == SW_OTHERUNZOOM || - msg->lParam == SW_OTHERZOOM) - break; - - if (GDK_WINDOW_DESTROYED (window)) - break; - - event = gdk_event_new (msg->wParam ? GDK_MAP : GDK_UNMAP); - event->any.window = window; - - _gdk_win32_append_event (event); - - if (event->any.type == GDK_UNMAP) - { - impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); - - if (impl->transient_owner && GetForegroundWindow () == GDK_WINDOW_HWND (window)) - { - SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner)); - } - - grab = _gdk_display_get_last_pointer_grab (_gdk_display); - if (grab != NULL) - { - if (grab->window == window) - gdk_pointer_ungrab (msg->time); - } - - if (_gdk_display->keyboard_grab.window == window) - gdk_keyboard_ungrab (msg->time); - } - - return_val = TRUE; - break; - case WM_SYSCOMMAND: switch (msg->wParam) { @@ -2659,85 +2875,32 @@ gdk_event_translate (MSG *msg, break; - case WM_SIZE: - GDK_NOTE (EVENTS, - g_print (" %s %dx%d", - (msg->wParam == SIZE_MAXHIDE ? "MAXHIDE" : - (msg->wParam == SIZE_MAXIMIZED ? "MAXIMIZED" : - (msg->wParam == SIZE_MAXSHOW ? "MAXSHOW" : - (msg->wParam == SIZE_MINIMIZED ? "MINIMIZED" : - (msg->wParam == SIZE_RESTORED ? "RESTORED" : "?"))))), - LOWORD (msg->lParam), HIWORD (msg->lParam))); - - if (msg->wParam == SIZE_MINIMIZED) - { - /* Don't generate any GDK event. This is *not* an UNMAP. */ - grab = _gdk_display_get_last_pointer_grab (_gdk_display); - if (grab != NULL) - { - if (grab->window == window) - gdk_pointer_ungrab (msg->time); - } - if (_gdk_display->keyboard_grab.window == window) - gdk_keyboard_ungrab (msg->time); - - gdk_synthesize_window_state (window, - GDK_WINDOW_STATE_WITHDRAWN, - GDK_WINDOW_STATE_ICONIFIED); - do_show_window (window, TRUE); - } - else if ((msg->wParam == SIZE_RESTORED || - msg->wParam == SIZE_MAXIMIZED) && - GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD) - { - GdkWindowState withdrawn_bit = - IsWindowVisible (msg->hwnd) ? GDK_WINDOW_STATE_WITHDRAWN : 0; - - if (((GdkWindowObject *) window)->state & GDK_WINDOW_STATE_ICONIFIED) - ensure_stacking_on_unminimize (msg); - - if (!GDK_WINDOW_DESTROYED (window)) - handle_configure_event (msg, window); - - if (msg->wParam == SIZE_RESTORED) - { - gdk_synthesize_window_state (window, - GDK_WINDOW_STATE_ICONIFIED | - GDK_WINDOW_STATE_MAXIMIZED | - withdrawn_bit, - 0); - - if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_TEMP && !GDK_WINDOW_IS_MAPPED (window)) - { - do_show_window (window, FALSE); - } - } - else if (msg->wParam == SIZE_MAXIMIZED) - { - gdk_synthesize_window_state (window, - GDK_WINDOW_STATE_ICONIFIED | - withdrawn_bit, - GDK_WINDOW_STATE_MAXIMIZED); - } - - if (((GdkWindowObject *) window)->resize_count > 1) - ((GdkWindowObject *) window)->resize_count -= 1; - - if (((GdkWindowObject *) window)->extension_events != 0) - _gdk_input_configure_event (window); - - return_val = TRUE; - } - break; - case WM_ENTERSIZEMOVE: case WM_ENTERMENULOOP: + if (msg->message == WM_ENTERSIZEMOVE) + _modal_move_resize_window = msg->hwnd; + _gdk_win32_begin_modal_call (); break; case WM_EXITSIZEMOVE: case WM_EXITMENULOOP: - _gdk_win32_end_modal_call (); + if (_modal_operation_in_progress) + { + _modal_move_resize_window = NULL; + _gdk_win32_end_modal_call (); + } + break; + + case WM_CAPTURECHANGED: + /* Sometimes we don't get WM_EXITSIZEMOVE, for instance when you + select move/size in the menu and then click somewhere without + moving/resizing. We work around this using WM_CAPTURECHANGED. */ + if (_modal_operation_in_progress) + { + _modal_move_resize_window = NULL; + _gdk_win32_end_modal_call (); + } break; case WM_WINDOWPOSCHANGING: @@ -2769,36 +2932,118 @@ gdk_event_translate (MSG *msg, buf))))), windowpos->cx, windowpos->cy, windowpos->x, windowpos->y)); - /* If position and size haven't changed, don't do anything */ - if (_modal_operation_in_progress && - (windowpos->flags & SWP_NOMOVE) && - (windowpos->flags & SWP_NOSIZE)) - break; - - /* Once we've entered the moving or sizing modal loop, we won't - * return to the main loop until we're done sizing or moving. - */ - if (_modal_operation_in_progress && - GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && - !GDK_WINDOW_DESTROYED (window)) + /* Break grabs on unmap or minimize */ + if (windowpos->flags & SWP_HIDEWINDOW || + ((windowpos->flags & SWP_STATECHANGED) && IsIconic (msg->hwnd))) { - if (((GdkWindowObject *) window)->event_mask & GDK_STRUCTURE_MASK) + grab = _gdk_display_get_last_pointer_grab (_gdk_display); + if (grab != NULL) { - GDK_NOTE (EVENTS, g_print (" do magic")); - if (((GdkWindowObject *) window)->resize_count > 1) - ((GdkWindowObject *) window)->resize_count -= 1; - - handle_configure_event (msg, window); - g_main_context_iteration (NULL, FALSE); -#if 0 - /* Dispatch main loop - to realize resizes... */ - modal_timer_proc (msg->hwnd, msg->message, 0, msg->time); -#endif - /* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */ - return_val = TRUE; - *ret_valp = 1; + if (grab->window == window) + gdk_pointer_ungrab (msg->time); } + + if (_gdk_display->keyboard_grab.window == window) + gdk_keyboard_ungrab (msg->time); } + + /* Send MAP events */ + if ((windowpos->flags & SWP_SHOWWINDOW) && + !GDK_WINDOW_DESTROYED (window)) + { + event = gdk_event_new (GDK_MAP); + event->any.window = window; + _gdk_win32_append_event (event); + } + + /* Update window state */ + if (windowpos->flags & (SWP_STATECHANGED | SWP_SHOWWINDOW | SWP_HIDEWINDOW)) + { + GdkWindowState set_bits, unset_bits, old_state, new_state; + + old_state = GDK_WINDOW_OBJECT (window)->state; + + set_bits = 0; + unset_bits = 0; + + if (IsWindowVisible (msg->hwnd)) + unset_bits |= GDK_WINDOW_STATE_WITHDRAWN; + else + set_bits |= GDK_WINDOW_STATE_WITHDRAWN; + + if (IsIconic (msg->hwnd)) + set_bits |= GDK_WINDOW_STATE_ICONIFIED; + else + unset_bits |= GDK_WINDOW_STATE_ICONIFIED; + + if (IsZoomed (msg->hwnd)) + set_bits |= GDK_WINDOW_STATE_MAXIMIZED; + else + unset_bits |= GDK_WINDOW_STATE_MAXIMIZED; + + gdk_synthesize_window_state (window, unset_bits, set_bits); + + new_state = GDK_WINDOW_OBJECT (window)->state; + + /* Whenever one window changes iconified state we need to also + * change the iconified state in all transient related windows, + * as windows doesn't give icons for transient childrens. + */ + if ((old_state & GDK_WINDOW_STATE_ICONIFIED) != + (new_state & GDK_WINDOW_STATE_ICONIFIED)) + do_show_window (window, (new_state & GDK_WINDOW_STATE_ICONIFIED)); + + + /* When un-minimizing, make sure we're stacked under any + transient-type windows. */ + if (!(old_state & GDK_WINDOW_STATE_ICONIFIED) && + (new_state & GDK_WINDOW_STATE_ICONIFIED)) + ensure_stacking_on_unminimize (msg); + } + + /* Show, New size or position => configure event */ + if (!(windowpos->flags & SWP_NOCLIENTMOVE) || + !(windowpos->flags & SWP_NOCLIENTSIZE) || + (windowpos->flags & SWP_SHOWWINDOW)) + { + if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && + !IsIconic (msg->hwnd) && + !GDK_WINDOW_DESTROYED (window)) + _gdk_win32_emit_configure_event (window); + + if (((GdkWindowObject *) window)->input_window != NULL) + _gdk_input_configure_event (window); + } + + if ((windowpos->flags & SWP_HIDEWINDOW) && + !GDK_WINDOW_DESTROYED (window)) + { + /* Send UNMAP events */ + event = gdk_event_new (GDK_UNMAP); + event->any.window = window; + _gdk_win32_append_event (event); + + /* Make transient parent the forground window when window unmaps */ + impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); + + if (impl->transient_owner && + GetForegroundWindow () == GDK_WINDOW_HWND (window)) + SetForegroundWindow (GDK_WINDOW_HWND (impl->transient_owner)); + } + + if (!(windowpos->flags & SWP_NOCLIENTSIZE)) + { + if (((GdkWindowObject *) window)->resize_count > 1) + ((GdkWindowObject *) window)->resize_count -= 1; + } + + /* Call modal timer immediate so that we repaint faster after a resize. */ + if (_modal_operation_in_progress) + modal_timer_proc (0,0,0,0); + + /* Claim as handled, so that WM_SIZE and WM_MOVE are avoided */ + return_val = TRUE; + *ret_valp = 0; break; case WM_SIZING: @@ -3070,20 +3315,9 @@ gdk_event_translate (MSG *msg, mmi->ptMaxSize.x, mmi->ptMaxSize.y)); return_val = TRUE; } - break; - - case WM_MOVE: - GDK_NOTE (EVENTS, g_print (" (%d,%d)", - GET_X_LPARAM (msg->lParam), GET_Y_LPARAM (msg->lParam))); - - if (GDK_WINDOW_TYPE (window) != GDK_WINDOW_CHILD && - !IsIconic (msg->hwnd)) - { - if (!GDK_WINDOW_DESTROYED (window)) - handle_configure_event (msg, window); - - return_val = TRUE; - } + mmi->ptMaxTrackSize.x = 30000; + mmi->ptMaxTrackSize.y = 30000; + return_val = TRUE; break; case WM_CLOSE: @@ -3105,7 +3339,7 @@ gdk_event_translate (MSG *msg, return_val = TRUE; break; - case WM_DESTROY: + case WM_NCDESTROY: grab = _gdk_display_get_last_pointer_grab (_gdk_display); if (grab != NULL) { @@ -3224,7 +3458,7 @@ gdk_event_translate (MSG *msg, * but we still need to deal with alt-tab, or with SetActiveWindow() type * situations. */ - if (is_modally_blocked (window) && LOWORD (msg->wParam) == WA_ACTIVE) + if (_gdk_modal_blocked (window) && LOWORD (msg->wParam) == WA_ACTIVE) { GdkWindow *modal_current = _gdk_modal_current (); SetActiveWindow (GDK_WINDOW_HWND (modal_current)); @@ -3273,8 +3507,7 @@ gdk_event_translate (MSG *msg, wintab: event = gdk_event_new (GDK_NOTHING); - event->any.window = window; - g_object_ref (window); + event->any.window = NULL; if (_gdk_input_other_event (event, msg, window)) _gdk_win32_append_event (event); @@ -3313,7 +3546,6 @@ static gboolean gdk_event_prepare (GSource *source, gint *timeout) { - MSG msg; gboolean retval; GDK_THREADS_ENTER (); @@ -3322,7 +3554,7 @@ gdk_event_prepare (GSource *source, retval = (_gdk_event_queue_find_first (_gdk_display) != NULL || (modal_win32_dialog == NULL && - PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE))); + GetQueueStatus (QS_ALLINPUT) != 0)); GDK_THREADS_LEAVE (); @@ -3332,7 +3564,6 @@ gdk_event_prepare (GSource *source, static gboolean gdk_event_check (GSource *source) { - MSG msg; gboolean retval; GDK_THREADS_ENTER (); @@ -3341,7 +3572,7 @@ gdk_event_check (GSource *source) { retval = (_gdk_event_queue_find_first (_gdk_display) != NULL || (modal_win32_dialog == NULL && - PeekMessageW (&msg, NULL, 0, 0, PM_NOREMOVE))); + GetQueueStatus (QS_ALLINPUT) != 0)); } else { @@ -3392,13 +3623,6 @@ gdk_win32_set_modal_dialog_libgtk_only (HWND window) modal_win32_dialog = window; } -static gboolean -is_modally_blocked (GdkWindow *window) -{ - GdkWindow *modal_current = _gdk_modal_current (); - return modal_current != NULL ? gdk_window_get_toplevel (window) != modal_current : FALSE; -} - static void check_for_too_much_data (GdkEvent *event) { @@ -3437,30 +3661,15 @@ gdk_screen_broadcast_client_message (GdkScreen *screen, void gdk_flush (void) { -#if 0 - MSG msg; - - /* Process all messages currently available */ - while (PeekMessageW (&msg, NULL, 0, 0, PM_REMOVE)) - { - TranslateMessage (&msg); - DispatchMessageW (&msg); - } -#endif - - GdiFlush (); + gdk_display_sync (_gdk_display); } void gdk_display_sync (GdkDisplay * display) { - MSG msg; - g_return_if_fail (display == _gdk_display); - /* Process all messages currently available */ - while (PeekMessageW (&msg, NULL, 0, 0, PM_REMOVE)) - DispatchMessageW (&msg); + GdiFlush (); } void @@ -3468,7 +3677,7 @@ gdk_display_flush (GdkDisplay * display) { g_return_if_fail (display == _gdk_display); - /* Nothing */ + GdiFlush (); } gboolean diff --git a/gdk/win32/gdkfont-win32.c b/gdk/win32/gdkfont-win32.c index e58a8d2543..9b81ce50b1 100644 --- a/gdk/win32/gdkfont-win32.c +++ b/gdk/win32/gdkfont-win32.c @@ -96,6 +96,7 @@ gdk_font_hash_lookup (GdkFontType type, } } +#ifdef G_ENABLE_DEBUG static const char * charset_name (DWORD charset) { @@ -122,6 +123,7 @@ charset_name (DWORD charset) } return "unknown"; } +#endif /* This table classifies Unicode characters according to the Microsoft * Unicode subset numbering. This is based on the table in "Developing @@ -366,6 +368,7 @@ static struct { U_SPECIALS, "Specials" } }; +#ifdef G_ENABLE_DEBUG static void print_unicode_subranges (FONTSIGNATURE *fsp) { @@ -387,6 +390,7 @@ print_unicode_subranges (FONTSIGNATURE *fsp) g_print (" none!"); g_print ("\n"); } +#endif static gboolean check_unicode_subranges (UINT charset, diff --git a/gdk/win32/gdkgc-win32.c b/gdk/win32/gdkgc-win32.c index 62f79292b6..712bc28585 100644 --- a/gdk/win32/gdkgc-win32.c +++ b/gdk/win32/gdkgc-win32.c @@ -205,7 +205,9 @@ gdk_win32_gc_values_to_win32values (GdkGCValues *values, GdkGCValuesMask mask, GdkGCWin32 *win32_gc) { +#ifdef G_ENABLE_DEBUG char *s = ""; +#endif GDK_NOTE (GC, g_print ("{")); diff --git a/gdk/win32/gdkglobals-win32.c b/gdk/win32/gdkglobals-win32.c index f9b2c024a5..1a876d0ec2 100644 --- a/gdk/win32/gdkglobals-win32.c +++ b/gdk/win32/gdkglobals-win32.c @@ -79,6 +79,7 @@ gint _gdk_input_ignore_wintab = FALSE; gint _gdk_max_colors = 0; gboolean _modal_operation_in_progress = FALSE; +HWND _modal_move_resize_window = NULL; gboolean _ignore_destroy_clipboard = FALSE; HGLOBAL _delayed_rendering_data = NULL; diff --git a/gdk/win32/gdkinput-win32.c b/gdk/win32/gdkinput-win32.c index 5dec13c1d8..3fe7aaf3de 100644 --- a/gdk/win32/gdkinput-win32.c +++ b/gdk/win32/gdkinput-win32.c @@ -58,16 +58,14 @@ static GList *wintab_contexts = NULL; static GdkWindow *wintab_window = NULL; -static GdkWindow *x_grab_window = NULL; /* Window that currently holds - * the extended inputs grab - */ -static GdkEventMask x_grab_mask; -static gboolean x_grab_owner_events; +static GdkDevicePrivate *_gdk_device_in_proximity; typedef UINT (WINAPI *t_WTInfoA) (UINT a, UINT b, LPVOID c); typedef UINT (WINAPI *t_WTInfoW) (UINT a, UINT b, LPVOID c); typedef BOOL (WINAPI *t_WTEnable) (HCTX a, BOOL b); typedef HCTX (WINAPI *t_WTOpenA) (HWND a, LPLOGCONTEXTA b, BOOL c); +typedef BOOL (WINAPI *t_WTGetA) (HCTX a, LPLOGCONTEXTA b); +typedef BOOL (WINAPI *t_WTSetA) (HCTX a, LPLOGCONTEXTA b); typedef BOOL (WINAPI *t_WTOverlap) (HCTX a, BOOL b); typedef BOOL (WINAPI *t_WTPacket) (HCTX a, UINT b, LPVOID c); typedef int (WINAPI *t_WTQueueSizeSet) (HCTX a, int b); @@ -76,6 +74,8 @@ static t_WTInfoA p_WTInfoA; static t_WTInfoW p_WTInfoW; static t_WTEnable p_WTEnable; static t_WTOpenA p_WTOpenA; +static t_WTGetA p_WTGetA; +static t_WTSetA p_WTSetA; static t_WTOverlap p_WTOverlap; static t_WTPacket p_WTPacket; static t_WTQueueSizeSet p_WTQueueSizeSet; @@ -97,8 +97,10 @@ gdk_input_find_dev_from_ctx (HCTX hctx, return NULL; } + #if DEBUG_WINTAB +#ifdef G_ENABLE_DEBUG static void print_lc(LOGCONTEXT *lc) { @@ -323,6 +325,7 @@ print_cursor (int index) } } #endif +#endif void _gdk_input_wintab_init_check (void) @@ -384,6 +387,10 @@ _gdk_input_wintab_init_check (void) return; if ((p_WTOpenA = (t_WTOpenA) GetProcAddress (wintab32, "WTOpenA")) == NULL) return; + if ((p_WTGetA = (t_WTGetA) GetProcAddress (wintab32, "WTGetA")) == NULL) + return; + if ((p_WTSetA = (t_WTSetA) GetProcAddress (wintab32, "WTSetA")) == NULL) + return; if ((p_WTOverlap = (t_WTOverlap) GetProcAddress (wintab32, "WTOverlap")) == NULL) return; if ((p_WTPacket = (t_WTPacket) GetProcAddress (wintab32, "WTPacket")) == NULL) @@ -461,7 +468,7 @@ _gdk_input_wintab_init_check (void) #if DEBUG_WINTAB GDK_NOTE (INPUT, (g_print("Default context:\n"), print_lc(&lc))); #endif - lc.lcOptions |= CXO_MESSAGES; + lc.lcOptions |= CXO_MESSAGES | CXO_CSRMESSAGES; lc.lcStatus = 0; lc.lcMsgBase = WT_DEFBASE; lc.lcPktRate = 0; @@ -471,8 +478,8 @@ _gdk_input_wintab_init_check (void) lc.lcBtnUpMask = lc.lcBtnDnMask = ~0; lc.lcOutOrgX = axis_x.axMin; lc.lcOutOrgY = axis_y.axMin; - lc.lcOutExtX = axis_x.axMax - axis_x.axMin; - lc.lcOutExtY = axis_y.axMax - axis_y.axMin; + lc.lcOutExtX = axis_x.axMax - axis_x.axMin + 1; + lc.lcOutExtY = axis_y.axMax - axis_y.axMin + 1; lc.lcOutExtY = -lc.lcOutExtY; /* We want Y growing downward */ #if DEBUG_WINTAB GDK_NOTE (INPUT, (g_print("context for device %d:\n", devix), @@ -488,9 +495,7 @@ _gdk_input_wintab_init_check (void) devix, *hctx)); wintab_contexts = g_list_append (wintab_contexts, hctx); -#if 0 - (*p_WTEnable) (*hctx, TRUE); -#endif + (*p_WTOverlap) (*hctx, TRUE); #if DEBUG_WINTAB @@ -502,7 +507,7 @@ _gdk_input_wintab_init_check (void) * with a smaller queue size. */ GDK_NOTE (INPUT, g_print("Attempting to increase queue size\n")); - for (i = 32; i >= 1; i >>= 1) + for (i = 128; i >= 1; i >>= 1) { if ((*p_WTQueueSizeSet) (*hctx, i)) { @@ -615,8 +620,8 @@ _gdk_input_wintab_init_check (void) gdkdev->axes[k].min_value = -1000; gdkdev->axes[k].max_value = 1000; gdkdev->info.axes[k].use = axis; - gdkdev->info.axes[k].min = -1000; - gdkdev->info.axes[k].max = 1000; + gdkdev->info.axes[k].min = -1.0; + gdkdev->info.axes[k].max = 1.0; k++; } } @@ -663,41 +668,44 @@ decode_tilt (gint *axis_data, static void gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, - GdkInputWindow *input_window, + GdkWindow *window, gint *axis_data, gdouble *axis_out, gdouble *x_out, gdouble *y_out) { + GdkWindowObject *priv, *impl_window; GdkWindowImplWin32 *root_impl; - GdkWindowObject *window_object; int i; int x_axis = 0; int y_axis = 0; - double device_width, device_height; + double device_width, device_height, x_min, y_min; double x_offset, y_offset, x_scale, y_scale; - window_object = GDK_WINDOW_OBJECT (input_window); + priv = (GdkWindowObject *) window; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); for (i=0; iinfo.num_axes; i++) { switch (gdkdev->info.axes[i].use) - { - case GDK_AXIS_X: - x_axis = i; - break; - case GDK_AXIS_Y: - y_axis = i; - break; - default: - break; - } + { + case GDK_AXIS_X: + x_axis = i; + break; + case GDK_AXIS_Y: + y_axis = i; + break; + default: + break; + } } device_width = gdkdev->axes[x_axis].max_value - gdkdev->axes[x_axis].min_value; + x_min = gdkdev->axes[x_axis].min_value; device_height = gdkdev->axes[y_axis].max_value - gdkdev->axes[y_axis].min_value; + y_min = gdkdev->axes[y_axis].min_value; if (gdkdev->info.mode == GDK_MODE_SCREEN) { @@ -705,56 +713,56 @@ gdk_input_translate_coordinates (GdkDevicePrivate *gdkdev, x_scale = GDK_WINDOW_OBJECT (_gdk_root)->width / device_width; y_scale = GDK_WINDOW_OBJECT (_gdk_root)->height / device_height; - x_offset = - input_window->root_x; - y_offset = - input_window->root_y; + x_offset = - impl_window->input_window->root_x - priv->abs_x; + y_offset = - impl_window->input_window->root_y - priv->abs_y; } else /* GDK_MODE_WINDOW */ { - double device_aspect = (device_height*gdkdev->axes[y_axis].resolution) / - (device_width*gdkdev->axes[x_axis].resolution); + double x_resolution = gdkdev->axes[x_axis].resolution; + double y_resolution = gdkdev->axes[y_axis].resolution; + double device_aspect = (device_height*y_resolution) / (device_width * x_resolution); - if (device_aspect * window_object->width >= window_object->height) - { - /* device taller than window */ - x_scale = window_object->width / device_width; - y_scale = (x_scale * gdkdev->axes[x_axis].resolution) / gdkdev->axes[y_axis].resolution; + if (device_aspect * priv->width >= priv->height) + { + /* device taller than window */ + x_scale = priv->width / device_width; + y_scale = (x_scale * x_resolution) / y_resolution; - x_offset = 0; - y_offset = -(device_height * y_scale - window_object->height) / 2; - } + x_offset = 0; + y_offset = -(device_height * y_scale - priv->height) / 2; + } else - { - /* window taller than device */ - y_scale = window_object->height / device_height; - x_scale = (y_scale * gdkdev->axes[y_axis].resolution) - / gdkdev->axes[x_axis].resolution; + { + /* window taller than device */ + y_scale = priv->height / device_height; + x_scale = (y_scale * y_resolution) / x_resolution; - y_offset = 0; - x_offset = - (device_width * x_scale - window_object->width) / 2; - } + y_offset = 0; + x_offset = - (device_width * x_scale - priv->width) / 2; + } } for (i = 0; i < gdkdev->info.num_axes; i++) { switch (gdkdev->info.axes[i].use) - { - case GDK_AXIS_X: - axis_out[i] = x_offset + x_scale * axis_data[x_axis]; - if (x_out) - *x_out = axis_out[i]; - break; - case GDK_AXIS_Y: - axis_out[i] = y_offset + y_scale * axis_data[y_axis]; - if (y_out) - *y_out = axis_out[i]; - break; - default: - axis_out[i] = - (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) + - gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) / - (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value); - break; - } + { + case GDK_AXIS_X: + axis_out[i] = x_offset + x_scale * axis_data[x_axis]; + if (x_out) + *x_out = axis_out[i]; + break; + case GDK_AXIS_Y: + axis_out[i] = y_offset + y_scale * axis_data[y_axis]; + if (y_out) + *y_out = axis_out[i]; + break; + default: + axis_out[i] = + (gdkdev->info.axes[i].max * (axis_data[i] - gdkdev->axes[i].min_value) + + gdkdev->info.axes[i].min * (gdkdev->axes[i].max_value - axis_data[i])) / + (gdkdev->axes[i].max_value - gdkdev->axes[i].min_value); + break; + } } } @@ -763,25 +771,30 @@ gdk_input_get_root_relative_geometry (HWND w, int *x_ret, int *y_ret) { - RECT rect; + POINT pt; - GetWindowRect (w, &rect); + pt.x = 0; + pt.y = 0; + ClientToScreen (w, &pt); if (x_ret) - *x_ret = rect.left + _gdk_offset_x; + *x_ret = pt.x + _gdk_offset_x; if (y_ret) - *y_ret = rect.top + _gdk_offset_y; + *y_ret = pt.y + _gdk_offset_y; } void _gdk_input_configure_event (GdkWindow *window) { GdkInputWindow *input_window; + GdkWindowObject *impl_window; int root_x, root_y; - input_window = _gdk_input_window_find (window); g_return_if_fail (window != NULL); + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + input_window = impl_window->input_window; + gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y); @@ -789,21 +802,6 @@ _gdk_input_configure_event (GdkWindow *window) input_window->root_y = root_y; } -void -_gdk_input_enter_event (GdkWindow *window) -{ - GdkInputWindow *input_window; - int root_x, root_y; - - input_window = _gdk_input_window_find (window); - g_return_if_fail (window != NULL); - - gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &root_x, &root_y); - - input_window->root_x = root_x; - input_window->root_y = root_y; -} - /* * Get the currently active keyboard modifiers (ignoring the mouse buttons) * We could use gdk_window_get_pointer but that function does a lot of other @@ -829,6 +827,7 @@ get_modifier_key_state (void) return state; } +#if 0 static guint ignore_core_timer = 0; static gboolean @@ -867,18 +866,78 @@ set_ignore_core (gboolean ignore) ignore_core_timefunc, NULL); } +#endif + +void +_gdk_input_update_for_device_mode (GdkDevicePrivate *gdkdev) +{ + LOGCONTEXT lc; + + if (gdkdev != _gdk_device_in_proximity) + return; + + if (p_WTGetA (gdkdev->hctx, &lc)) + { + if (gdkdev->info.mode == GDK_MODE_SCREEN && + (lc.lcOptions & CXO_SYSTEM) == 0) + { + lc.lcOptions |= CXO_SYSTEM; + p_WTSetA (gdkdev->hctx, &lc); + } + else if (gdkdev->info.mode == GDK_MODE_WINDOW && + (lc.lcOptions & CXO_SYSTEM) != 0) + { + lc.lcOptions &= ~CXO_SYSTEM; + p_WTSetA (gdkdev->hctx, &lc); + } + } +} + +static GdkWindow * +find_window_for_input_event (MSG* msg, int *x, int *y) +{ + POINT pt; + GdkWindow *window; + HWND hwnd; + RECT rect; + + pt = msg->pt; + + window = NULL; + hwnd = WindowFromPoint (pt); + if (hwnd != NULL) + { + POINT client_pt = pt; + + ScreenToClient (hwnd, &client_pt); + GetClientRect (hwnd, &rect); + if (PtInRect (&rect, client_pt)) + window = gdk_win32_handle_table_lookup ((GdkNativeWindow) hwnd); + } + + /* need to also adjust the coordinates to the new window */ + if (window) + ScreenToClient (GDK_WINDOW_HWND (window), &pt); + + *x = pt.x; + *y = pt.y; + + if (window) + return window; + + return _gdk_root; +} + gboolean _gdk_input_other_event (GdkEvent *event, MSG *msg, GdkWindow *window) { - GdkDisplay *display; - GdkWindowObject *obj, *grab_obj; + GdkWindowObject *obj, *impl_window; + GdkWindow *native_window; GdkInputWindow *input_window; GdkDevicePrivate *gdkdev = NULL; - GdkEventMask masktest; guint key_state; - POINT pt; PACKET packet; gint k; @@ -889,31 +948,24 @@ _gdk_input_other_event (GdkEvent *event, */ static guint button_map[8] = {0, 1, 4, 5, 2, 3, 6, 7}; - if (event->any.window != wintab_window) + if (window != wintab_window) { g_warning ("_gdk_input_other_event: not wintab_window?"); return FALSE; } - window = gdk_window_at_pointer (&x, &y); - if (window == NULL) - window = _gdk_root; - - g_object_ref (window); - display = gdk_drawable_get_display (window); + native_window = find_window_for_input_event (msg, &x, &y); GDK_NOTE (EVENTS_OR_INPUT, - g_print ("_gdk_input_other_event: window=%p %+d%+d\n", - GDK_WINDOW_HWND (window), x, y)); - - if (msg->message == WT_PACKET) + g_print ("_gdk_input_other_event: native_window=%p %+d%+d\n", + GDK_WINDOW_HWND (native_window), x, y)); + + if (msg->message == WT_PACKET || msg->message == WT_CSRCHANGE) { if (!(*p_WTPacket) ((HCTX) msg->lParam, msg->wParam, &packet)) return FALSE; } - obj = GDK_WINDOW_OBJECT (window); - switch (msg->message) { case WT_PACKET: @@ -925,11 +977,6 @@ _gdk_input_other_event (GdkEvent *event, GDK_NOTE (EVENTS_OR_INPUT, g_print ("... ignored when moving/sizing\n")); return FALSE; } - if (window == _gdk_root && x_grab_window == NULL) - { - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... is root\n")); - return FALSE; - } if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam, packet.pkCursor)) == NULL) @@ -979,104 +1026,50 @@ _gdk_input_other_event (GdkEvent *event, } if (!(translated_buttons & button_mask)) - { - event->any.type = GDK_BUTTON_RELEASE; - masktest = GDK_BUTTON_RELEASE_MASK; - } + event->any.type = GDK_BUTTON_RELEASE; else - { - event->any.type = GDK_BUTTON_PRESS; - masktest = GDK_BUTTON_PRESS_MASK; - } + event->any.type = GDK_BUTTON_PRESS; gdkdev->button_state ^= button_mask; } else { event->any.type = GDK_MOTION_NOTIFY; - masktest = GDK_POINTER_MOTION_MASK; - if (gdkdev->button_state & (1 << 0)) - masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON1_MOTION_MASK; - if (gdkdev->button_state & (1 << 1)) - masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON2_MOTION_MASK; - if (gdkdev->button_state & (1 << 2)) - masktest |= GDK_BUTTON_MOTION_MASK | GDK_BUTTON3_MOTION_MASK; } - /* See if input is grabbed */ - /* FIXME: x_grab_owner_events should probably be handled somehow */ - if (x_grab_window != NULL) - { - grab_obj = GDK_WINDOW_OBJECT (x_grab_window); - if (!GDK_WINDOW_IMPL_WIN32 (grab_obj->impl)->extension_events_selected - || !(grab_obj->extension_events & masktest) - || !(x_grab_mask && masktest)) - { - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("... grabber doesn't want it\n")); - return FALSE; - } - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... to grabber\n")); + if (native_window == _gdk_root) + return FALSE; - g_object_ref(x_grab_window); - g_object_unref(window); - window = x_grab_window; - obj = grab_obj; - } - /* Now we can check if the window wants the event, and - * propagate if necessary. - */ - loop: - if (!GDK_WINDOW_IMPL_WIN32 (obj->impl)->extension_events_selected - || !(obj->extension_events & masktest)) - { - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... not selected\n")); + window = _gdk_window_get_input_window_for_event (native_window, + event->any.type, + gdkdev->button_state << 8, + x, y, 0); - if (obj->parent == GDK_WINDOW_OBJECT (_gdk_root)) - return FALSE; + obj = GDK_WINDOW_OBJECT (window); - /* It is not good to propagate the extended events up to the parent - * if this window wants normal (not extended) motion/button events */ - if (obj->event_mask & masktest) - { - GDK_NOTE (EVENTS_OR_INPUT, - g_print ("... wants ordinary event, ignoring this\n")); - return FALSE; - } - - pt.x = x; - pt.y = y; - ClientToScreen (GDK_WINDOW_HWND (window), &pt); - g_object_unref (window); - window = (GdkWindow *) obj->parent; - obj = GDK_WINDOW_OBJECT (window); - g_object_ref (window); - ScreenToClient (GDK_WINDOW_HWND (window), &pt); - x = pt.x; - y = pt.y; - GDK_NOTE (EVENTS_OR_INPUT, g_print ("... propagating to %p %+d%+d\n", - GDK_WINDOW_HWND (window), x, y)); - goto loop; - } - - input_window = _gdk_input_window_find (window); + if (window == NULL || + obj->extension_events == 0) + return FALSE; + + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + input_window = impl_window->input_window; g_assert (input_window != NULL); - if (gdkdev->info.mode == GDK_MODE_WINDOW - && input_window->mode == GDK_EXTENSION_EVENTS_CURSOR) + if (gdkdev->info.mode == GDK_MODE_WINDOW && + (obj->extension_events & GDK_ALL_DEVICES_MASK) == 0) return FALSE; event->any.window = window; key_state = get_modifier_key_state (); - if (event->any.type == GDK_BUTTON_PRESS - || event->any.type == GDK_BUTTON_RELEASE) + if (event->any.type == GDK_BUTTON_PRESS || + event->any.type == GDK_BUTTON_RELEASE) { event->button.time = _gdk_win32_get_next_tick (msg->time); event->button.device = &gdkdev->info; event->button.axes = g_new(gdouble, gdkdev->info.num_axes); - gdk_input_translate_coordinates (gdkdev, input_window, + gdk_input_translate_coordinates (gdkdev, window, gdkdev->last_axis_data, event->button.axes, &event->button.x, @@ -1107,7 +1100,7 @@ _gdk_input_other_event (GdkEvent *event, event->motion.axes = g_new(gdouble, gdkdev->info.num_axes); - gdk_input_translate_coordinates (gdkdev, input_window, + gdk_input_translate_coordinates (gdkdev, window, gdkdev->last_axis_data, event->motion.axes, &event->motion.x, @@ -1130,49 +1123,104 @@ _gdk_input_other_event (GdkEvent *event, } return TRUE; - case WT_PROXIMITY: - if (LOWORD (msg->lParam) == 0) - { - event->proximity.type = GDK_PROXIMITY_OUT; - set_ignore_core (FALSE); - } - else + case WT_CSRCHANGE: + if ((gdkdev = gdk_input_find_dev_from_ctx ((HCTX) msg->lParam, + packet.pkCursor)) == NULL) + return FALSE; + + _gdk_device_in_proximity = gdkdev; + + _gdk_input_update_for_device_mode (gdkdev); + + window = NULL; + if (native_window != _gdk_root) + window = _gdk_window_get_input_window_for_event (native_window, + GDK_PROXIMITY_IN, + 0, + x, y, 0); + if (window) { event->proximity.type = GDK_PROXIMITY_IN; - set_ignore_core (TRUE); + event->proximity.window = window; + event->proximity.time = _gdk_win32_get_next_tick (msg->time); + event->proximity.device = &_gdk_device_in_proximity->info; } - event->proximity.time = _gdk_win32_get_next_tick (msg->time); - event->proximity.device = &gdkdev->info; GDK_NOTE (EVENTS_OR_INPUT, - g_print ("WINTAB proximity %s\n", - (event->proximity.type == GDK_PROXIMITY_IN ? - "in" : "out"))); + g_print ("WINTAB proximity in\n")); + return TRUE; + + case WT_PROXIMITY: + /* TODO: Set ignore_core if in input_window */ + if (LOWORD (msg->lParam) == 0) + { + _gdk_input_in_proximity = FALSE; + + window = NULL; + if (native_window != _gdk_root) + window = _gdk_window_get_input_window_for_event (native_window, + GDK_PROXIMITY_IN, + 0, + x, y, 0); + if (window) + { + event->proximity.type = GDK_PROXIMITY_OUT; + event->proximity.window = window; + event->proximity.time = _gdk_win32_get_next_tick (msg->time); + event->proximity.device = &_gdk_device_in_proximity->info; + } + + GDK_NOTE (EVENTS_OR_INPUT, + g_print ("WINTAB proximity out\n")); + + return TRUE; + } + else + _gdk_input_in_proximity = TRUE; + + _gdk_input_check_proximity (); + + break; } return FALSE; } -gboolean -_gdk_input_enable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev) +void +_gdk_input_select_events (GdkWindow *impl_window) { - GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); + guint event_mask; + GdkWindowObject *w; + GdkInputWindow *iw; + GList *l, *dev_list; + - impl->extension_events_selected = TRUE; + iw = ((GdkWindowObject *)impl_window)->input_window; - return TRUE; -} + event_mask = 0; + for (dev_list = _gdk_input_devices; dev_list; dev_list = dev_list->next) + { + GdkDevicePrivate *gdkdev = dev_list->data; -gboolean -_gdk_input_disable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev) -{ - GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); + if (!GDK_IS_CORE (gdkdev) && + gdkdev->info.mode != GDK_MODE_DISABLED && + iw != NULL) + { + for (l = iw->windows; l != NULL; l = l->next) + { + w = l->data; + if (gdkdev->info.has_cursor || (w->extension_events & GDK_ALL_DEVICES_MASK)) + event_mask |= w->extension_events; + } + } + } + + event_mask &= ~GDK_ALL_DEVICES_MASK; + if (event_mask) + event_mask |= + GDK_PROXIMITY_OUT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK; - impl->extension_events_selected = FALSE; - - return TRUE; + GDK_WINDOW_IMPL_WIN32 (((GdkWindowObject *)impl_window)->impl)->extension_events_mask = event_mask; } gint @@ -1182,131 +1230,20 @@ _gdk_input_grab_pointer (GdkWindow *window, GdkWindow *confine_to, guint32 time) { - GdkInputWindow *input_window, *new_window; - gboolean need_ungrab; - GdkDevicePrivate *gdkdev; - GList *tmp_list; - - tmp_list = _gdk_input_windows; - new_window = NULL; - need_ungrab = FALSE; - GDK_NOTE (INPUT, g_print ("_gdk_input_grab_pointer: %p %d %p\n", GDK_WINDOW_HWND (window), owner_events, (confine_to ? GDK_WINDOW_HWND (confine_to) : 0))); - while (tmp_list) - { - input_window = (GdkInputWindow *)tmp_list->data; - - if (input_window->window == window) - new_window = input_window; - else if (input_window->grabbed) - { - input_window->grabbed = FALSE; - need_ungrab = TRUE; - } - - tmp_list = tmp_list->next; - } - - if (new_window) - { - new_window->grabbed = TRUE; - x_grab_window = window; - x_grab_mask = event_mask; - x_grab_owner_events = owner_events; - - /* FIXME: Do we need to handle confine_to and time? */ - - tmp_list = _gdk_input_devices; - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *)tmp_list->data; - if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx) - { -#if 0 - /* XXX */ - gdk_input_common_find_events (window, gdkdev, - event_mask, - event_classes, &num_classes); - - result = XGrabDevice( GDK_DISPLAY(), gdkdev->xdevice, - GDK_WINDOW_XWINDOW (window), - owner_events, num_classes, event_classes, - GrabModeAsync, GrabModeAsync, time); - - /* FIXME: if failure occurs on something other than the first - device, things will be badly inconsistent */ - if (result != Success) - return result; -#endif - } - tmp_list = tmp_list->next; - } - } - else - { - x_grab_window = NULL; -#if 0 - tmp_list = _gdk_input_devices; - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *)tmp_list->data; - if (!GDK_IS_CORE (gdkdev) && gdkdev->hctx && - ((gdkdev->button_state != 0) || need_ungrab)) - { -#if 0 - /* XXX */ - XUngrabDevice (gdk_display, gdkdev->xdevice, time); -#endif - gdkdev->button_state = 0; - } - - tmp_list = tmp_list->next; - } -#endif - } - return GDK_GRAB_SUCCESS; } void _gdk_input_ungrab_pointer (guint32 time) { - GdkInputWindow *input_window; - GdkDevicePrivate *gdkdev; - GList *tmp_list; GDK_NOTE (INPUT, g_print ("_gdk_input_ungrab_pointer\n")); - tmp_list = _gdk_input_windows; - while (tmp_list) - { - input_window = (GdkInputWindow *)tmp_list->data; - if (input_window->grabbed) - break; - tmp_list = tmp_list->next; - } - - if (tmp_list) /* we found a grabbed window */ - { - input_window->grabbed = FALSE; - - tmp_list = _gdk_input_devices; - while (tmp_list) - { - gdkdev = (GdkDevicePrivate *)tmp_list->data; -#if 0 - /* XXX */ - if (!GDK_IS_CORE (gdkdev) && gdkdev->xdevice) - XUngrabDevice (gdk_display, gdkdev->xdevice, time); -#endif - tmp_list = tmp_list->next; - } - } - x_grab_window = NULL; } gboolean @@ -1344,7 +1281,6 @@ gdk_device_get_state (GdkDevice *device, else { GdkDevicePrivate *gdkdev; - GdkInputWindow *input_window; gdkdev = (GdkDevicePrivate *)device; /* For now just use the last known button and axis state of the device. @@ -1359,12 +1295,10 @@ gdk_device_get_state (GdkDevice *device, | GDK_BUTTON3_MASK | GDK_BUTTON4_MASK | GDK_BUTTON5_MASK)); } - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); /* For some reason, input_window is sometimes NULL when I use The GIMP 2 * (bug #141543?). Avoid crashing if debugging is disabled. */ - if (axes && gdkdev->last_axis_data && input_window) - gdk_input_translate_coordinates (gdkdev, input_window, + if (axes && gdkdev->last_axis_data) + gdk_input_translate_coordinates (gdkdev, window, gdkdev->last_axis_data, axes, NULL, NULL); } @@ -1397,7 +1331,6 @@ _gdk_input_set_tablet_active (void) void _gdk_input_init (GdkDisplay *display) { - _gdk_input_ignore_core = FALSE; _gdk_input_devices = NULL; _gdk_init_input_core (display); diff --git a/gdk/win32/gdkinput-win32.h b/gdk/win32/gdkinput-win32.h index 608d8f99d6..746bcaf30e 100644 --- a/gdk/win32/gdkinput-win32.h +++ b/gdk/win32/gdkinput-win32.h @@ -70,24 +70,19 @@ struct _GdkDevicePrivate AXIS orientation_axes[2]; }; +/* Addition used for extension_events mask */ +#define GDK_ALL_DEVICES_MASK (1<<30) + struct _GdkInputWindow { /* gdk window */ - GdkWindow *window; + GList *windows; /* GdkWindow:s with extension_events set */ - /* Extension mode (GDK_EXTENSION_EVENTS_ALL/CURSOR) */ - GdkExtensionMode mode; + GdkWindow *impl_window; /* an impl window */ /* position relative to root window */ gint root_x; gint root_y; - - /* rectangles relative to window of windows obscuring this one */ - GdkRectangle *obscuring; - gint num_obscuring; - - /* Is there a pointer grab for this window ? */ - gint grabbed; }; /* Global data */ @@ -97,7 +92,7 @@ struct _GdkInputWindow extern GList *_gdk_input_devices; extern GList *_gdk_input_windows; -extern gint _gdk_input_ignore_core; +extern gboolean _gdk_input_in_proximity; /* Function declarations */ void _gdk_init_input_core (GdkDisplay *display); @@ -109,7 +104,6 @@ GdkTimeCoord ** _gdk_device_allocate_history (GdkDevice *device, * (just wintab for now) */ void _gdk_input_configure_event (GdkWindow *window); -void _gdk_input_enter_event (GdkWindow *window); gboolean _gdk_input_other_event (GdkEvent *event, MSG *msg, GdkWindow *window); @@ -124,10 +118,7 @@ GdkInputWindow *_gdk_input_window_find (GdkWindow *window); void _gdk_input_window_destroy (GdkWindow *window); -gint _gdk_input_enable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev); -gint _gdk_input_disable_window (GdkWindow *window, - GdkDevicePrivate *gdkdev); +void _gdk_input_select_events (GdkWindow *impl_window); gint _gdk_input_grab_pointer (GdkWindow *window, gint owner_events, GdkEventMask event_mask, @@ -143,5 +134,7 @@ gboolean _gdk_device_get_history (GdkDevice *device, void _gdk_input_wintab_init_check (void); void _gdk_input_set_tablet_active (void); +void _gdk_input_update_for_device_mode (GdkDevicePrivate *gdkdev); +void _gdk_input_check_proximity (void); #endif /* __GDK_INPUT_WIN32_H__ */ diff --git a/gdk/win32/gdkinput.c b/gdk/win32/gdkinput.c index 2612afb1fc..c38644369c 100644 --- a/gdk/win32/gdkinput.c +++ b/gdk/win32/gdkinput.c @@ -46,10 +46,10 @@ static GdkDeviceAxis gdk_input_core_axes[] = { /* Global variables */ -gint _gdk_input_ignore_core; - GList *_gdk_input_devices; GList *_gdk_input_windows; +gboolean _gdk_input_in_proximity = 0; +gboolean _gdk_input_inside_input_window = 0; void _gdk_init_input_core (GdkDisplay *display) @@ -291,30 +291,63 @@ gdk_device_free_history (GdkTimeCoord **events, g_free (events); } -GdkInputWindow * -_gdk_input_window_find(GdkWindow *window) -{ - GList *tmp_list; - - for (tmp_list=_gdk_input_windows; tmp_list; tmp_list=tmp_list->next) - if (((GdkInputWindow *)(tmp_list->data))->window == window) - return (GdkInputWindow *)(tmp_list->data); - - return NULL; /* Not found */ -} - /* FIXME: this routine currently needs to be called between creation and the corresponding configure event (because it doesn't get the root_relative_geometry). This should work with gtk_window_set_extension_events, but will likely fail in other cases */ +static void +unset_extension_events (GdkWindow *window) +{ + GdkWindowObject *window_private; + GdkWindowObject *impl_window; + GdkInputWindow *iw; + + window_private = (GdkWindowObject*) window; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + iw = impl_window->input_window; + + if (window_private->extension_events != 0) + { + g_assert (iw != NULL); + g_assert (g_list_find (iw->windows, window) != NULL); + + iw->windows = g_list_remove (iw->windows, window); + if (iw->windows == NULL) + { + impl_window->input_window = NULL; + _gdk_input_windows = g_list_remove(_gdk_input_windows,iw); + g_free (iw); + } + } + + window_private->extension_events = 0; +} + +static void +gdk_input_get_root_relative_geometry (HWND w, + int *x_ret, + int *y_ret) +{ + POINT pt; + + pt.x = 0; + pt.y = 0; + ClientToScreen (w, &pt); + + if (x_ret) + *x_ret = pt.x + _gdk_offset_x; + if (y_ret) + *y_ret = pt.y + _gdk_offset_y; +} + void gdk_input_set_extension_events (GdkWindow *window, gint mask, GdkExtensionMode mode) { GdkWindowObject *window_private; - GList *tmp_list; + GdkWindowObject *impl_window; GdkInputWindow *iw; g_return_if_fail (window != NULL); @@ -324,68 +357,81 @@ gdk_input_set_extension_events (GdkWindow *window, gint mask, if (GDK_WINDOW_DESTROYED (window)) return; + impl_window = (GdkWindowObject *)_gdk_window_get_impl_window (window); + + if (mode == GDK_EXTENSION_EVENTS_ALL && mask != 0) + mask |= GDK_ALL_DEVICES_MASK; + if (mode == GDK_EXTENSION_EVENTS_NONE) mask = 0; + iw = impl_window->input_window; + if (mask != 0) { _gdk_input_wintab_init_check (); - iw = g_new(GdkInputWindow,1); + if (!iw) + { + iw = g_new0 (GdkInputWindow,1); - iw->window = window; - iw->mode = mode; + iw->impl_window = (GdkWindow *)impl_window; - iw->obscuring = NULL; - iw->num_obscuring = 0; - iw->grabbed = FALSE; + iw->windows = NULL; - _gdk_input_windows = g_list_append(_gdk_input_windows,iw); + _gdk_input_windows = g_list_append(_gdk_input_windows, iw); + + gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), &iw->root_x, &iw->root_y); + + impl_window->input_window = iw; + } + + if (window_private->extension_events == 0) + iw->windows = g_list_append (iw->windows, window); window_private->extension_events = mask; - - /* Add enter window events to the event mask */ - if (g_list_length (_gdk_input_devices) > 1) - gdk_window_set_events (window, - gdk_window_get_events (window) | - GDK_ENTER_NOTIFY_MASK); } else { - iw = _gdk_input_window_find (window); - if (iw) - { - _gdk_input_windows = g_list_remove(_gdk_input_windows,iw); - g_free(iw); - } - - window_private->extension_events = 0; + unset_extension_events (window); } - for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next) - { - GdkDevicePrivate *gdkdev = tmp_list->data; - - if (!GDK_IS_CORE (gdkdev)) - { - if (mask != 0 && gdkdev->info.mode != GDK_MODE_DISABLED - && (gdkdev->info.has_cursor || mode == GDK_EXTENSION_EVENTS_ALL)) - _gdk_input_enable_window (window,gdkdev); - else - _gdk_input_disable_window (window,gdkdev); - } - } + _gdk_input_select_events ((GdkWindow *)impl_window); } void _gdk_input_window_destroy (GdkWindow *window) { - GdkInputWindow *input_window; + unset_extension_events (window); +} - input_window = _gdk_input_window_find (window); - g_return_if_fail (input_window != NULL); +void +_gdk_input_check_proximity (void) +{ + GList *l; + gboolean new_proximity = FALSE; - _gdk_input_windows = g_list_remove (_gdk_input_windows,input_window); - g_free(input_window); + if (!_gdk_input_inside_input_window) + { + _gdk_display->ignore_core_events = FALSE; + return; + } + + for (l = _gdk_input_devices; l != NULL; l = l->next) + { + GdkDevicePrivate *gdkdev = l->data; + + if (gdkdev->info.mode != GDK_MODE_DISABLED && + !GDK_IS_CORE (gdkdev)) + { + if (_gdk_input_in_proximity) + { + new_proximity = TRUE; + break; + } + } + } + + _gdk_display->ignore_core_events = new_proximity; } void @@ -394,53 +440,27 @@ _gdk_input_crossing_event (GdkWindow *window, { if (enter) { -#if 0 /* No idea what to do... */ GdkWindowObject *priv = (GdkWindowObject *)window; GdkInputWindow *input_window; gint root_x, root_y; -#if 0 - gdk_input_check_proximity(display); -#endif + + _gdk_input_inside_input_window = TRUE; + input_window = priv->input_window; if (input_window != NULL) { - _gdk_input_get_root_relative_geometry (window, &root_x, &root_y); + gdk_input_get_root_relative_geometry (GDK_WINDOW_HWND (window), + &root_x, &root_y); input_window->root_x = root_x; input_window->root_y = root_y; } -#endif } else - _gdk_input_ignore_core = FALSE; -} - -void -_gdk_input_exit (void) -{ - GList *tmp_list; - GdkDevicePrivate *gdkdev; - - for (tmp_list = _gdk_input_devices; tmp_list; tmp_list = tmp_list->next) { - gdkdev = (GdkDevicePrivate *)(tmp_list->data); - if (!GDK_IS_CORE (gdkdev)) - { - gdk_device_set_mode (&gdkdev->info, GDK_MODE_DISABLED); - - g_free(gdkdev->info.name); - g_free(gdkdev->axes); - g_free(gdkdev->info.axes); - g_free(gdkdev->info.keys); - g_free(gdkdev); - } + _gdk_input_inside_input_window = FALSE; } - g_list_free(_gdk_input_devices); - - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - g_free(tmp_list->data); - - g_list_free(_gdk_input_windows); + _gdk_input_check_proximity (); } gboolean @@ -473,7 +493,6 @@ gdk_device_set_mode (GdkDevice *device, { GList *tmp_list; GdkDevicePrivate *gdkdev; - GdkInputMode old_mode; GdkInputWindow *input_window; if (GDK_IS_CORE (device)) @@ -484,39 +503,21 @@ gdk_device_set_mode (GdkDevice *device, if (device->mode == mode) return TRUE; - old_mode = device->mode; device->mode = mode; if (mode == GDK_MODE_WINDOW) - { - device->has_cursor = FALSE; - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - { - input_window = (GdkInputWindow *)tmp_list->data; - if (input_window->mode != GDK_EXTENSION_EVENTS_CURSOR) - _gdk_input_enable_window (input_window->window, gdkdev); - else - if (old_mode != GDK_MODE_DISABLED) - _gdk_input_disable_window (input_window->window, gdkdev); - } - } + device->has_cursor = FALSE; else if (mode == GDK_MODE_SCREEN) + device->has_cursor = TRUE; + + for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) { - device->has_cursor = TRUE; - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - _gdk_input_enable_window (((GdkInputWindow *)tmp_list->data)->window, - gdkdev); - } - else /* mode == GDK_MODE_DISABLED */ - { - for (tmp_list = _gdk_input_windows; tmp_list; tmp_list = tmp_list->next) - { - input_window = (GdkInputWindow *)tmp_list->data; - if (old_mode != GDK_MODE_WINDOW || - input_window->mode != GDK_EXTENSION_EVENTS_CURSOR) - _gdk_input_disable_window (input_window->window, gdkdev); - } + input_window = (GdkInputWindow *)tmp_list->data; + _gdk_input_select_events (input_window->impl_window); } + if (!GDK_IS_CORE (gdkdev)) + _gdk_input_update_for_device_mode (gdkdev); + return TRUE; } diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h index 1f961d2b06..78995331a8 100644 --- a/gdk/win32/gdkprivate-win32.h +++ b/gdk/win32/gdkprivate-win32.h @@ -305,7 +305,7 @@ void _gdk_wchar_text_handle (GdkFont *font, void _gdk_push_modal_window (GdkWindow *window); void _gdk_remove_modal_window (GdkWindow *window); GdkWindow *_gdk_modal_current (void); - +gboolean _gdk_modal_blocked (GdkWindow *window); #ifdef G_ENABLE_DEBUG gchar *_gdk_win32_color_to_string (const GdkColor *color); @@ -467,6 +467,8 @@ extern gint _gdk_max_colors; /* 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 */ extern gboolean _ignore_destroy_clipboard; @@ -491,7 +493,9 @@ HICON _gdk_win32_pixbuf_to_hcursor (GdkPixbuf *pixbuf, gboolean _gdk_win32_pixbuf_to_hicon_supports_alpha (void); void _gdk_win32_append_event (GdkEvent *event); - +void _gdk_win32_emit_configure_event (GdkWindow *window); +GdkWindow *_gdk_win32_find_window_for_mouse_event (GdkWindow* reported_window, + MSG* msg); /* Initialization */ void _gdk_windowing_window_init (GdkScreen *screen); diff --git a/gdk/win32/gdkselection-win32.c b/gdk/win32/gdkselection-win32.c index e3936a9b3e..86f42b2a61 100644 --- a/gdk/win32/gdkselection-win32.c +++ b/gdk/win32/gdkselection-win32.c @@ -584,14 +584,14 @@ gdk_selection_convert (GdkWindow *requestor, * it. * * If the data is from Mozilla Firefox or IE7, and - * starts with an "oldfashioned" BITMAPINFOHEADER, + * starts with an "old fashioned" BITMAPINFOHEADER, * i.e. with biSize==40, and biCompression == BI_RGB and * biBitCount==32, we assume that the "extra" byte in * each pixel in fact is alpha. * * The gdk-pixbuf bmp loader doesn't trust 32-bit BI_RGB - * nitmaps to in fact have alpha, so we have to convince - * it by changint the bitmap header to a version 5 + * bitmaps to in fact have alpha, so we have to convince + * it by changing the bitmap header to a version 5 * BI_BITFIELDS one with explicit alpha mask indicated. * * The RGB bytes that are in bitmaps on the clipboard @@ -718,6 +718,17 @@ gdk_selection_convert (GdkWindow *requestor, bi->biSize + bi->biClrUsed * sizeof (RGBQUAD)); + if (bi->biCompression == BI_BITFIELDS && bi->biBitCount >= 16) + { + /* Screenshots taken with PrintScreen or + * Alt + PrintScreen are found on the clipboard in + * this format. In this case the BITMAPINFOHEADER is + * followed by three DWORD specifying the masks of the + * red green and blue components, so adjust the offset + * accordingly. */ + bf->bfOffBits += (3 * sizeof (DWORD)); + } + memcpy ((char *) data + sizeof (BITMAPFILEHEADER), bi, data_length); diff --git a/gdk/win32/gdkwin32.h b/gdk/win32/gdkwin32.h index 1f03097d8a..32777ad29c 100644 --- a/gdk/win32/gdkwin32.h +++ b/gdk/win32/gdkwin32.h @@ -77,6 +77,7 @@ G_BEGIN_DECLS /* Return true if the GdkWindow is a win32 implemented window */ gboolean gdk_win32_window_is_win32 (GdkWindow *window); +HWND gdk_win32_window_get_impl_hwnd (GdkWindow *window); /* Return the Gdk* for a particular HANDLE */ gpointer gdk_win32_handle_table_lookup (GdkNativeWindow handle); diff --git a/gdk/win32/gdkwindow-win32.c b/gdk/win32/gdkwindow-win32.c index d895262547..867e343cc4 100644 --- a/gdk/win32/gdkwindow-win32.c +++ b/gdk/win32/gdkwindow-win32.c @@ -46,6 +46,15 @@ static void gdk_window_impl_win32_finalize (GObject *object); static gpointer parent_class = NULL; static GSList *modal_window_stack = NULL; +typedef struct _FullscreenInfo FullscreenInfo; + +struct _FullscreenInfo +{ + RECT r; + guint hint_flags; + LONG style; +}; + static void update_style_bits (GdkWindow *window); static gboolean _gdk_window_get_functions (GdkWindow *window, GdkWMFunction *functions); @@ -116,7 +125,7 @@ gdk_window_impl_win32_init (GdkWindowImplWin32 *impl) impl->hicon_small = NULL; impl->hint_flags = 0; impl->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; - impl->extension_events_selected = FALSE; + impl->extension_events_mask = 0; impl->transient_owner = NULL; impl->transient_children = NULL; impl->num_transients = 0; @@ -497,9 +506,10 @@ _gdk_window_impl_new (GdkWindow *window, GdkDrawableImplWin32 *draw_impl; const gchar *title; wchar_t *wtitle; + gboolean override_redirect; gint window_width, window_height; gint offset_x = 0, offset_y = 0; - gint x, y; + gint x, y, real_x = 0, real_y = 0; /* check consistency of redundant information */ guint remaining_mask = attributes_mask; @@ -527,8 +537,12 @@ _gdk_window_impl_new (GdkWindow *window, g_assert (attributes->y == private->y); remaining_mask &= ~GDK_WA_Y; } + override_redirect = FALSE; if ((attributes_mask & GDK_WA_NOREDIR) != 0) - remaining_mask &= ~GDK_WA_NOREDIR; + { + override_redirect = !!attributes->override_redirect; + remaining_mask &= ~GDK_WA_NOREDIR; + } if ((remaining_mask & ~(GDK_WA_WMCLASS|GDK_WA_VISUAL|GDK_WA_CURSOR|GDK_WA_COLORMAP|GDK_WA_TITLE|GDK_WA_TYPE_HINT)) != 0) g_warning ("_gdk_window_impl_new: uexpected attribute 0x%X", @@ -544,7 +558,8 @@ _gdk_window_impl_new (GdkWindow *window, if (attributes_mask & GDK_WA_VISUAL) g_assert (visual == attributes->visual); - impl->extension_events_selected = FALSE; + impl->extension_events_mask = 0; + impl->override_redirect = override_redirect; /* wclass is not any longer set always, but if is ... */ if ((attributes_mask & GDK_WA_WMCLASS) == GDK_WA_WMCLASS) @@ -634,8 +649,22 @@ _gdk_window_impl_new (GdkWindow *window, AdjustWindowRectEx (&rect, dwStyle, FALSE, dwExStyle); - /* non child windows are placed by the OS/window manager */ - x = y = CW_USEDEFAULT; + real_x = private->x - offset_x; + real_y = private->y - offset_y; + + if (private->window_type == GDK_WINDOW_TOPLEVEL || + private->window_type == GDK_WINDOW_DIALOG) + { + /* We initially place it at default so that we can get the + default window positioning if we want */ + x = y = CW_USEDEFAULT; + } + else + { + /* TEMP, FOREIGN: Put these where requested */ + x = real_x; + y = real_y; + } window_width = rect.right - rect.left; window_height = rect.bottom - rect.top; @@ -657,7 +686,7 @@ _gdk_window_impl_new (GdkWindow *window, if (!title || !*title) title = ""; - private->event_mask = GDK_STRUCTURE_MASK | event_mask; + impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask; if (attributes_mask & GDK_WA_TYPE_HINT) gdk_window_set_type_hint (window, attributes->type_hint); @@ -702,6 +731,21 @@ _gdk_window_impl_new (GdkWindow *window, } + if (private->window_type != GDK_WINDOW_CHILD) + { + GetWindowRect (GDK_WINDOW_HWND (window), &rect); + impl->initial_x = rect.left; + impl->initial_y = rect.top; + + /* Now we know the initial position, move to actually specified position */ + if (real_x != x || real_y != y) + { + API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL, + real_x, real_y, 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER)); + } + } + g_object_ref (window); gdk_win32_handle_table_insert (&GDK_WINDOW_HWND (window), window); @@ -826,9 +870,6 @@ _gdk_win32_window_destroy (GdkWindow *window, GDK_NOTE (MISC, g_print ("_gdk_win32_window_destroy: %p\n", GDK_WINDOW_HWND (window))); - if (private->extension_events != 0) - _gdk_input_window_destroy (window); - /* Remove ourself from the modal stack */ _gdk_remove_modal_window (window); @@ -858,8 +899,6 @@ _gdk_win32_window_destroy (GdkWindow *window, private->destroyed = TRUE; DestroyWindow (GDK_WINDOW_HWND (window)); } - - gdk_win32_handle_table_remove (GDK_WINDOW_HWND (window)); } void @@ -926,7 +965,9 @@ adjust_for_gravity_hints (GdkWindow *window, if (impl->hint_flags & GDK_HINT_WIN_GRAVITY) { +#ifdef G_ENABLE_DEBUG gint orig_x = *x, orig_y = *y; +#endif switch (impl->hints.win_gravity) { @@ -985,34 +1026,32 @@ adjust_for_gravity_hints (GdkWindow *window, static void show_window_internal (GdkWindow *window, - gboolean raise, + gboolean already_mapped, gboolean deiconify) { GdkWindowObject *private; - HWND old_active_window; - gboolean focus_on_map = TRUE; + GdkWindowImplWin32 *window_impl; + gboolean focus_on_map = FALSE; DWORD exstyle; - HWND top; private = (GdkWindowObject *) window; if (private->destroyed) return; - GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s%s\n", + GDK_NOTE (MISC, g_print ("show_window_internal: %p: %s%s\n", GDK_WINDOW_HWND (window), _gdk_win32_window_state_to_string (private->state), - (raise ? " raise" : ""), (deiconify ? " deiconify" : ""))); /* If asked to show (not deiconify) an withdrawn and iconified * window, do that. */ if (!deiconify && - !GDK_WINDOW_IS_MAPPED (window) && + !already_mapped && (private->state & GDK_WINDOW_STATE_ICONIFIED)) { - ShowWindow (GDK_WINDOW_HWND (window), SW_MINIMIZE); + ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWMINNOACTIVE); return; } @@ -1030,50 +1069,153 @@ show_window_internal (GdkWindow *window, /* If asked to show (but not raise) a window that is already * visible, do nothing. */ - if (!deiconify && !raise && IsWindowVisible (GDK_WINDOW_HWND (window))) + if (!deiconify && !already_mapped && IsWindowVisible (GDK_WINDOW_HWND (window))) return; /* Other cases */ - if (!GDK_WINDOW_IS_MAPPED (window)) - { - gdk_synthesize_window_state (window, - GDK_WINDOW_STATE_WITHDRAWN, - 0); - focus_on_map = private->focus_on_map; - } + if (!already_mapped) + focus_on_map = private->focus_on_map; exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE); - if (private->state & GDK_WINDOW_STATE_BELOW) - exstyle &= (~WS_EX_TOPMOST); - - if (private->state & GDK_WINDOW_STATE_ABOVE) - exstyle |= WS_EX_TOPMOST; - - if (exstyle & WS_EX_TOPMOST) - top = HWND_TOPMOST; - else - top = HWND_TOP; - /* Use SetWindowPos to show transparent windows so automatic redraws * in other windows can be suppressed. */ if (exstyle & WS_EX_TRANSPARENT) { - UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE; + UINT flags = SWP_SHOWWINDOW | SWP_NOREDRAW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER; - if (!raise) - flags |= SWP_NOZORDER; - if (!raise || GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map) + if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map) flags |= SWP_NOACTIVATE; - SetWindowPos (GDK_WINDOW_HWND (window), top, 0, 0, 0, 0, flags); + SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOP, 0, 0, 0, 0, flags); return; } - old_active_window = GetActiveWindow (); + /* For initial map of "normal" windows we want to emulate WM window + * positioning behaviour, which means: + * + Use user specified position if GDK_HINT_POS or GDK_HINT_USER_POS + * otherwise: + * + default to the initial CW_USEDEFAULT placement, + * no matter if the user moved the window before showing it. + * + Certain window types and hints have more elaborate positioning + * schemes. + */ + window_impl = GDK_WINDOW_IMPL_WIN32 (private->impl); + if (!already_mapped && + (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL || + GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG) && + (window_impl->hint_flags & (GDK_HINT_POS | GDK_HINT_USER_POS)) == 0 && + !window_impl->override_redirect) + { + gboolean center = FALSE; + RECT window_rect, center_on_rect; + int x, y; + + x = window_impl->initial_x; + y = window_impl->initial_y; + + if (window_impl->type_hint == GDK_WINDOW_TYPE_HINT_SPLASHSCREEN) + { + HMONITOR monitor; + MONITORINFO mi; + + monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof (mi); + if (monitor && GetMonitorInfo (monitor, &mi)) + center_on_rect = mi.rcMonitor; + else + { + center_on_rect.left = 0; + center_on_rect.right = 0; + center_on_rect.right = GetSystemMetrics (SM_CXSCREEN); + center_on_rect.bottom = GetSystemMetrics (SM_CYSCREEN); + } + center = TRUE; + } + else if (window_impl->transient_owner != NULL && + GDK_WINDOW_IS_MAPPED (window_impl->transient_owner)) + { + GdkWindowObject *owner = GDK_WINDOW_OBJECT (window_impl->transient_owner); + /* Center on transient parent */ + center_on_rect.left = owner->x; + center_on_rect.top = owner->y; + center_on_rect.right = center_on_rect.left + owner->width; + center_on_rect.bottom = center_on_rect.top + owner->height; + _gdk_win32_adjust_client_rect (GDK_WINDOW (owner), ¢er_on_rect); + center = TRUE; + } + + if (center) + { + window_rect.left = 0; + window_rect.top = 0; + window_rect.right = private->width; + window_rect.bottom = private->height; + _gdk_win32_adjust_client_rect (window, &window_rect); + + x = center_on_rect.left + ((center_on_rect.right - center_on_rect.left) - (window_rect.right - window_rect.left)) / 2; + y = center_on_rect.top + ((center_on_rect.bottom - center_on_rect.top) - (window_rect.bottom - window_rect.top)) / 2; + } + + API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL, + x, y, 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER)); + } + + if (!already_mapped && + (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL || + GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG) && + !window_impl->override_redirect) + { + /* Ensure new windows are fully onscreen */ + RECT window_rect; + HMONITOR monitor; + MONITORINFO mi; + int x, y; + + GetWindowRect (GDK_WINDOW_HWND (window), &window_rect); + + monitor = MonitorFromWindow (GDK_WINDOW_HWND (window), MONITOR_DEFAULTTONEAREST); + mi.cbSize = sizeof (mi); + if (monitor && GetMonitorInfo (monitor, &mi)) + { + x = window_rect.left; + y = window_rect.top; + + if (window_rect.right > mi.rcWork.right) + { + window_rect.left -= (window_rect.right - mi.rcWork.right); + window_rect.right -= (window_rect.right - mi.rcWork.right); + } + + if (window_rect.bottom > mi.rcWork.bottom) + { + window_rect.top -= (window_rect.bottom - mi.rcWork.bottom); + window_rect.bottom -= (window_rect.bottom - mi.rcWork.bottom); + } + + if (window_rect.left < mi.rcWork.left) + { + window_rect.right += (mi.rcWork.left - window_rect.left); + window_rect.left += (mi.rcWork.left - window_rect.left); + } + + if (window_rect.top < mi.rcWork.top) + { + window_rect.bottom += (mi.rcWork.top - window_rect.top); + window_rect.top += (mi.rcWork.top - window_rect.top); + } + + if (x != window_rect.left || y != window_rect.top) + API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), NULL, + window_rect.left, window_rect.top, 0, 0, + SWP_NOACTIVATE | SWP_NOSIZE | SWP_NOZORDER)); + } + } + if (private->state & GDK_WINDOW_STATE_FULLSCREEN) { @@ -1085,7 +1227,10 @@ show_window_internal (GdkWindow *window, } else if (private->state & GDK_WINDOW_STATE_ICONIFIED) { - ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE); + if (focus_on_map) + ShowWindow (GDK_WINDOW_HWND (window), SW_RESTORE); + else + ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNOACTIVATE); } else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP || !focus_on_map) { @@ -1096,38 +1241,16 @@ show_window_internal (GdkWindow *window, ShowWindow (GDK_WINDOW_HWND (window), SW_SHOWNORMAL); } - if (raise) + /* Sync STATE_ABOVE to TOPMOST */ + if (((private->state & GDK_WINDOW_STATE_ABOVE) && + !(exstyle & WS_EX_TOPMOST)) || + (!(private->state & GDK_WINDOW_STATE_ABOVE) && + (exstyle & WS_EX_TOPMOST))) { - if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TEMP) - SetWindowPos (GDK_WINDOW_HWND (window), HWND_TOPMOST, - 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - else if (GDK_WINDOW_TYPE (window) == GDK_WINDOW_TOPLEVEL || - GDK_WINDOW_TYPE (window) == GDK_WINDOW_DIALOG) - { - if (focus_on_map && private->accept_focus) - { - SetForegroundWindow (GDK_WINDOW_HWND (window)); - if (top == HWND_TOPMOST) - SetWindowPos (GDK_WINDOW_HWND (window), top, - 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - } - else - { - SetWindowPos (GDK_WINDOW_HWND (window), top, - 0, 0, 0, 0, - SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE); - } - } - else - { - BringWindowToTop (GDK_WINDOW_HWND (window)); - } - } - else if (old_active_window != GDK_WINDOW_HWND (window)) - { - SetActiveWindow (old_active_window); + API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), + (private->state & GDK_WINDOW_STATE_ABOVE)?HWND_TOPMOST:HWND_NOTOPMOST, + 0, 0, 0, 0, + SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE)); } } @@ -1351,6 +1474,17 @@ gdk_win32_window_move_resize (GdkWindow *window, gint width, gint height) { + GdkWindowObject *private = (GdkWindowObject *)window; + GdkWindowImplWin32 *window_impl; + + window_impl = GDK_WINDOW_IMPL_WIN32 (private->impl); + window_impl->inhibit_configure = TRUE; + + /* We ignore changes to the window being moved or resized by the + user, as we don't want to fight the user */ + if (GDK_WINDOW_HWND (window) == _modal_move_resize_window) + goto out; + if (with_move && (width < 0 && height < 0)) { gdk_win32_window_move (window, x, y); @@ -1366,6 +1500,12 @@ gdk_win32_window_move_resize (GdkWindow *window, gdk_win32_window_resize (window, width, height); } } + + out: + window_impl->inhibit_configure = FALSE; + + if (WINDOW_IS_TOPLEVEL (window)) + _gdk_win32_emit_configure_event (window); } static gboolean @@ -1872,6 +2012,7 @@ gdk_window_set_geometry_hints (GdkWindow *window, GdkWindowHints geom_mask) { GdkWindowImplWin32 *impl; + FullscreenInfo *fi; g_return_if_fail (GDK_IS_WINDOW (window)); @@ -1883,7 +2024,11 @@ gdk_window_set_geometry_hints (GdkWindow *window, impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); - impl->hint_flags = geom_mask; + fi = g_object_get_data (G_OBJECT (window), "fullscreen-info"); + if (fi) + fi->hint_flags = geom_mask; + else + impl->hint_flags = geom_mask; impl->hints = *geometry; if (geom_mask & GDK_HINT_POS) @@ -2069,24 +2214,40 @@ _gdk_remove_modal_window (GdkWindow *window) } } +gboolean +_gdk_modal_blocked (GdkWindow *window) +{ + GSList *l; + gboolean found_any = FALSE; + + for (l = modal_window_stack; l != NULL; l = l->next) + { + GdkWindow *modal = l->data; + + if (modal == window) + return FALSE; + + if (GDK_WINDOW_IS_MAPPED (modal)) + found_any = TRUE; + } + + return found_any; +} + GdkWindow * _gdk_modal_current (void) { - if (modal_window_stack != NULL) - { - GSList *tmp = modal_window_stack; + GSList *l; - while (tmp != NULL && !GDK_WINDOW_IS_MAPPED (tmp->data)) - { - tmp = g_slist_next (tmp); - } - - return tmp != NULL ? tmp->data : NULL; - } - else + for (l = modal_window_stack; l != NULL; l = l->next) { - return NULL; + GdkWindow *modal = l->data; + + if (GDK_WINDOW_IS_MAPPED (modal)) + return modal; } + + return NULL; } static void @@ -2581,6 +2742,16 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display, screen_to_client (hwnd, screen_pt, &client_pt); hwndc = ChildWindowFromPointEx (hwnd, client_pt, CWP_SKIPDISABLED | CWP_SKIPINVISIBLE); + + /* Verify that we're really inside the client area of the window */ + if (hwndc != hwnd) + { + GetClientRect (hwndc, &rect); + screen_to_client (hwndc, screen_pt, &client_pt); + if (!PtInRect (&rect, client_pt)) + hwndc = hwnd; + } + } while (hwndc != hwnd && (hwnd = hwndc, 1)); } @@ -2588,6 +2759,12 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display, { hwnd = WindowFromPoint (screen_pt); + /* Verify that we're really inside the client area of the window */ + GetClientRect (hwnd, &rect); + screen_to_client (hwnd, screen_pt, &client_pt); + if (!PtInRect (&rect, client_pt)) + hwnd = NULL; + /* If we didn't hit any window at that point, return the desktop */ if (hwnd == NULL) { @@ -2603,13 +2780,10 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display, if (window && (win_x || win_y)) { - screen_to_client (hwnd, screen_pt, &client_pt); - GetClientRect (hwnd, &rect); - if (win_x) - *win_x = client_pt.x - rect.left; + *win_x = client_pt.x; if (win_y) - *win_y = client_pt.y - rect.top; + *win_y = client_pt.y; } GDK_NOTE (MISC, g_print ("_gdk_windowing_window_at_pointer: %+d%+d %p%s\n", @@ -2623,21 +2797,29 @@ _gdk_windowing_window_at_pointer (GdkDisplay *display, static GdkEventMask gdk_win32_window_get_events (GdkWindow *window) { + GdkWindowImplWin32 *impl; + if (GDK_WINDOW_DESTROYED (window)) return 0; - return GDK_WINDOW_OBJECT (window)->event_mask; + impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); + + return impl->native_event_mask; } static void gdk_win32_window_set_events (GdkWindow *window, - GdkEventMask event_mask) + GdkEventMask event_mask) { + GdkWindowImplWin32 *impl; + + impl = GDK_WINDOW_IMPL_WIN32 (GDK_WINDOW_OBJECT (window)->impl); + /* gdk_window_new() always sets the GDK_STRUCTURE_MASK, so better * set it here, too. Not that I know or remember why it is * necessary, will have to test some day. */ - GDK_WINDOW_OBJECT (window)->event_mask = GDK_STRUCTURE_MASK | event_mask; + impl->native_event_mask = GDK_STRUCTURE_MASK | event_mask; } static void @@ -2700,9 +2882,15 @@ void gdk_window_set_override_redirect (GdkWindow *window, gboolean override_redirect) { + GdkWindowObject *private; + GdkWindowImplWin32 *window_impl; + g_return_if_fail (GDK_IS_WINDOW (window)); - g_warning ("gdk_window_set_override_redirect not implemented"); + private = (GdkWindowObject *) window; + window_impl = GDK_WINDOW_IMPL_WIN32 (private->impl); + + window_impl->override_redirect = !!override_redirect; } void @@ -2912,6 +3100,9 @@ update_style_bits (GdkWindow *window) gboolean all; RECT rect, before, after; + if (private->state & GDK_WINDOW_STATE_FULLSCREEN) + return; + old_style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE); old_exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE); @@ -3107,7 +3298,7 @@ gboolean _gdk_window_get_functions (GdkWindow *window, GdkWMFunction *functions) { - GdkWMDecoration* functions_set; + GdkWMFunction* functions_set; functions_set = g_object_get_qdata (G_OBJECT (window), get_functions_quark ()); if (functions_set) @@ -3271,7 +3462,7 @@ gdk_window_deiconify (GdkWindow *window) if (GDK_WINDOW_IS_MAPPED (window)) { - show_window_internal (window, FALSE, TRUE); + show_window_internal (window, GDK_WINDOW_IS_MAPPED (window), TRUE); } else { @@ -3343,15 +3534,6 @@ gdk_window_unmaximize (GdkWindow *window) 0); } -typedef struct _FullscreenInfo FullscreenInfo; - -struct _FullscreenInfo -{ - RECT r; - guint hint_flags; - LONG style; -}; - void gdk_window_fullscreen (GdkWindow *window) { @@ -3393,14 +3575,15 @@ gdk_window_fullscreen (GdkWindow *window) g_object_set_data (G_OBJECT (window), "fullscreen-info", fi); fi->style = GetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE); + /* Send state change before configure event */ + gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN); + SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, (fi->style & ~WS_OVERLAPPEDWINDOW) | WS_POPUP); API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_TOP, x, y, width, height, SWP_NOCOPYBITS | SWP_SHOWWINDOW)); - - gdk_synthesize_window_state (window, 0, GDK_WINDOW_STATE_FULLSCREEN); } } @@ -3417,6 +3600,8 @@ gdk_window_unfullscreen (GdkWindow *window) { GdkWindowImplWin32 *impl = GDK_WINDOW_IMPL_WIN32 (private->impl); + gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0); + impl->hint_flags = fi->hint_flags; SetWindowLong (GDK_WINDOW_HWND (window), GWL_STYLE, fi->style); API_CALL (SetWindowPos, (GDK_WINDOW_HWND (window), HWND_NOTOPMOST, @@ -3426,8 +3611,7 @@ gdk_window_unfullscreen (GdkWindow *window) g_object_set_data (G_OBJECT (window), "fullscreen-info", NULL); g_free (fi); - - gdk_synthesize_window_state (window, GDK_WINDOW_STATE_FULLSCREEN, 0); + update_style_bits (window); } } @@ -3451,10 +3635,10 @@ gdk_window_set_keep_above (GdkWindow *window, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE)); } - else - gdk_synthesize_window_state (window, - setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE, - setting ? GDK_WINDOW_STATE_ABOVE : 0); + + gdk_synthesize_window_state (window, + setting ? GDK_WINDOW_STATE_BELOW : GDK_WINDOW_STATE_ABOVE, + setting ? GDK_WINDOW_STATE_ABOVE : 0); } void @@ -3477,10 +3661,10 @@ gdk_window_set_keep_below (GdkWindow *window, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE | SWP_NOACTIVATE)); } - else - gdk_synthesize_window_state (window, - setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW, - setting ? GDK_WINDOW_STATE_BELOW : 0); + + gdk_synthesize_window_state (window, + setting ? GDK_WINDOW_STATE_ABOVE : GDK_WINDOW_STATE_BELOW, + setting ? GDK_WINDOW_STATE_BELOW : 0); } void @@ -3725,9 +3909,9 @@ gdk_window_set_opacity (GdkWindow *window, exstyle = GetWindowLong (GDK_WINDOW_HWND (window), GWL_EXSTYLE); if (!(exstyle & WS_EX_LAYERED)) - API_CALL (SetWindowLong, (GDK_WINDOW_HWND (window), - GWL_EXSTYLE, - exstyle | WS_EX_LAYERED)); + SetWindowLong (GDK_WINDOW_HWND (window), + GWL_EXSTYLE, + exstyle | WS_EX_LAYERED); setLayeredWindowAttributes = (PFN_SetLayeredWindowAttributes)GetProcAddress (GetModuleHandle ("user32.dll"), "SetLayeredWindowAttributes"); @@ -3906,6 +4090,15 @@ gdk_win32_window_is_win32 (GdkWindow *window) return GDK_WINDOW_IS_WIN32 (window); } +HWND +gdk_win32_window_get_impl_hwnd (GdkWindow *window) +{ + if (GDK_WINDOW_IS_WIN32 (window)) + return GDK_WINDOW_HWND (window); + return NULL; +} + + GdkDrawable * gdk_win32_begin_direct_draw_libgtk_only (GdkDrawable *drawable, GdkGC *gc, diff --git a/gdk/win32/gdkwindow-win32.h b/gdk/win32/gdkwindow-win32.h index f488e59faa..096db338cb 100644 --- a/gdk/win32/gdkwindow-win32.h +++ b/gdk/win32/gdkwindow-win32.h @@ -80,16 +80,23 @@ struct _GdkWindowImplWin32 gint hint_flags; GdkGeometry hints; + GdkEventMask native_event_mask; + GdkWindowTypeHint type_hint; - gboolean extension_events_selected; + GdkEventMask extension_events_mask; GdkWindow *transient_owner; GSList *transient_children; gint num_transients; gboolean changing_state; + gint initial_x; + gint initial_y; + guint no_bg : 1; + guint inhibit_configure : 1; + guint override_redirect : 1; }; struct _GdkWindowImplWin32Class diff --git a/gdk/x11/gdkinput-xfree.c b/gdk/x11/gdkinput-xfree.c index bf63959f31..5d87ccd21e 100644 --- a/gdk/x11/gdkinput-xfree.c +++ b/gdk/x11/gdkinput-xfree.c @@ -266,6 +266,8 @@ _gdk_input_other_event (GdkEvent *event, else window = _gdk_window_get_input_window_for_event (event_window, event_type, + /* TODO: Seems wrong, but the code used to ignore button motion handling here... */ + 0, x, y, xevent->xany.serial); priv = (GdkWindowObject *)window; diff --git a/gtk/gtkfilechooserdefault.c b/gtk/gtkfilechooserdefault.c index 256cc207c6..d05de4fd01 100644 --- a/gtk/gtkfilechooserdefault.c +++ b/gtk/gtkfilechooserdefault.c @@ -3630,6 +3630,8 @@ shortcuts_pane_create (GtkFileChooserDefault *impl, /* Box for buttons */ toolbar = gtk_toolbar_new (); + gtk_toolbar_set_style (GTK_TOOLBAR (toolbar), GTK_TOOLBAR_ICONS); + gtk_toolbar_set_icon_size (GTK_TOOLBAR (toolbar), GTK_ICON_SIZE_MENU); gtk_box_pack_start (GTK_BOX (vbox), toolbar, FALSE, FALSE, 0); diff --git a/gtk/gtkprintoperation-win32.c b/gtk/gtkprintoperation-win32.c index c0d149c2a6..0c29298649 100644 --- a/gtk/gtkprintoperation-win32.c +++ b/gtk/gtkprintoperation-win32.c @@ -72,7 +72,7 @@ static void win32_poll_status (GtkPrintOperation *op); static const GUID myIID_IPrintDialogCallback = {0x5852a2c3,0x6530,0x11d1,{0xb6,0xa3,0x0,0x0,0xf8,0x75,0x7b,0xf9}}; -#if !defined (_MSC_VER) && !defined (__MINGW64_VERSION_MAJOR) +#if !defined (_MSC_VER) && !defined (HAVE_IPRINTDIALOGCALLBACK) #undef INTERFACE #define INTERFACE IPrintDialogCallback DECLARE_INTERFACE_ (IPrintDialogCallback, IUnknown) diff --git a/gtk/gtksettings.c b/gtk/gtksettings.c index de96b91bbe..f83a54b89e 100644 --- a/gtk/gtksettings.c +++ b/gtk/gtksettings.c @@ -292,7 +292,11 @@ gtk_settings_class_init (GtkSettingsClass *class) g_param_spec_string ("gtk-theme-name", P_("Theme Name"), P_("Name of theme RC file to load"), +#ifdef G_OS_WIN32 + "MS-Windows", +#else "Raleigh", +#endif GTK_PARAM_READWRITE), NULL); g_assert (result == PROP_THEME_NAME); diff --git a/gtk/gtkstatusicon.c b/gtk/gtkstatusicon.c index 04fe1cb087..77d93da6a2 100644 --- a/gtk/gtkstatusicon.c +++ b/gtk/gtkstatusicon.c @@ -114,6 +114,7 @@ struct _GtkStatusIconPrivate #ifdef GDK_WINDOWING_WIN32 GtkWidget *dummy_widget; NOTIFYICONDATAW nid; + gint taskbar_top; gint last_click_x, last_click_y; GtkOrientation orientation; gchar *tooltip_text; @@ -889,6 +890,8 @@ gtk_status_icon_init (GtkStatusIcon *status_icon) priv->orientation = GTK_ORIENTATION_VERTICAL; else priv->orientation = GTK_ORIENTATION_HORIZONTAL; + + priv->taskbar_top = abd.rc.top; } priv->last_click_x = priv->last_click_y = 0; @@ -2568,6 +2571,7 @@ gtk_status_icon_position_menu (GtkMenu *menu, #ifdef GDK_WINDOWING_WIN32 GtkStatusIcon *status_icon; GtkStatusIconPrivate *priv; + GtkRequisition menu_req; g_return_if_fail (GTK_IS_MENU (menu)); g_return_if_fail (GTK_IS_STATUS_ICON (user_data)); @@ -2575,8 +2579,11 @@ gtk_status_icon_position_menu (GtkMenu *menu, status_icon = GTK_STATUS_ICON (user_data); priv = status_icon->priv; + gtk_widget_size_request (GTK_WIDGET (menu), &menu_req); + *x = priv->last_click_x; - *y = priv->last_click_y; + *y = priv->taskbar_top - menu_req.height; + *push_in = TRUE; #endif } diff --git a/modules/engines/ms-windows/msw_style.c b/modules/engines/ms-windows/msw_style.c index 771d6965ef..9be99aa692 100755 --- a/modules/engines/ms-windows/msw_style.c +++ b/modules/engines/ms-windows/msw_style.c @@ -41,7 +41,7 @@ #include #include -#include "gtk/gtk.h" +#include "gdk/gdk.h" #include "gtk/gtk.h" #ifdef BUILDING_STANDALONE @@ -660,8 +660,9 @@ setup_msw_rc_style (void) btn_face.red, btn_face.green, btn_face.blue); gtk_rc_parse_string (buf); - /* enable coloring for text on buttons TODO: use GetThemeMetric for the - border and outside border */ + /* enable coloring for text on buttons + * TODO: use GetThemeMetric for the border and outside border + * TODO: child-displacement-x & y should be 0 when XP theme is active */ g_snprintf (buf, sizeof (buf), "style \"msw-button\" = \"msw-default\"\n" "{\n" @@ -849,7 +850,7 @@ setup_system_styles (GtkStyle *style) sys_color_to_gtk_color (XP_THEME_CLASS_TEXT, COLOR_GRAYTEXT, &style->fg[GTK_STATE_INSENSITIVE]); sys_color_to_gtk_color (XP_THEME_CLASS_BUTTON, COLOR_BTNTEXT, - &style->bg[GTK_STATE_ACTIVE]); + &style->fg[GTK_STATE_ACTIVE]); sys_color_to_gtk_color (XP_THEME_CLASS_WINDOW, COLOR_WINDOWTEXT, &style->fg[GTK_STATE_PRELIGHT]); @@ -2347,231 +2348,290 @@ DrawTab (HDC hdc, const RECT R, gint32 aPosition, gboolean aSelected, DrawEdge (hdc, &shadeRect, EDGE_RAISED, BF_SOFT | shadeFlag); } +static void +get_notebook_tab_position (GtkNotebook *notebook, + gboolean *start, + gboolean *end) +{ + gboolean found_start = FALSE, found_end = FALSE; + gint i, n_pages; + + /* default value */ + *start = TRUE; + *end = FALSE; + + n_pages = gtk_notebook_get_n_pages (notebook); + for (i = 0; i < n_pages; i++) + { + GtkWidget *tab_child; + GtkWidget *tab_label; + gboolean expand; + GtkPackType pack_type; + gboolean is_selected; + + tab_child = gtk_notebook_get_nth_page (notebook, i); + is_selected = gtk_notebook_get_current_page (notebook) == i; + + /* Skip invisible tabs */ + tab_label = gtk_notebook_get_tab_label (notebook, tab_child); + if (!tab_label || !GTK_WIDGET_VISIBLE (tab_label)) + continue; + + /* Mimics what the notebook does internally. */ + if (tab_label && !gtk_widget_get_child_visible (tab_label)) + { + /* One child is hidden because scroll arrows are present. + * So both corners are rounded. */ + *start = FALSE; + *end = FALSE; + return; + } + + gtk_notebook_query_tab_label_packing (notebook, tab_child, &expand, + NULL, /* don't need fill */ + &pack_type); + + if (pack_type == GTK_PACK_START) + { + if (!found_start) + { + /* This is the first tab with PACK_START pack type */ + found_start = TRUE; + + if (is_selected) + { + /* first PACK_START item is selected: set start to TRUE */ + *start = TRUE; + + if (expand && !found_end) + { + /* tentatively set end to TRUE: will be invalidated if we + * find other items */ + *end = TRUE; + } + } + else + { + *start = FALSE; + } + } + else if (!found_end && !is_selected) + { + /* an unselected item exists, and no item with PACK_END pack type */ + *end = FALSE; + } + } + + if (pack_type == GTK_PACK_END) + { + if (!found_end) + { + /* This is the first tab with PACK_END pack type */ + found_end = TRUE; + + if (is_selected) + { + /* first PACK_END item is selected: set end to TRUE */ + *end = TRUE; + + if (expand && !found_start) + { + /* tentatively set start to TRUE: will be invalidated if + * we find other items */ + *start = TRUE; + } + } + else + { + *end = FALSE; + } + } + else if (!found_start && !is_selected) + { + *start = FALSE; + } + } + } +} + static gboolean draw_themed_tab_button (GtkStyle *style, GdkWindow *window, GtkStateType state_type, GtkNotebook *notebook, - gint x, gint y, - gint width, gint height, gint gap_side) + gint x, + gint y, + gint width, + gint height, + gint gap_side) { GdkPixmap *pixmap = NULL; - gint border_width = - gtk_container_get_border_width (GTK_CONTAINER (notebook)); - GtkWidget *widget = GTK_WIDGET (notebook); GdkRectangle draw_rect, clip_rect; - GdkPixbufRotation rotation = GDK_PIXBUF_ROTATE_NONE; cairo_t *cr; + gboolean start, stop; + XpThemeElement element; + gint d_w, d_h; - if (gap_side == GTK_POS_TOP) + get_notebook_tab_position (notebook, &start, &stop); + + if (state_type == GTK_STATE_NORMAL) { - int widget_right; - - if (state_type == GTK_STATE_NORMAL) - { - draw_rect.x = x; - draw_rect.y = y; - draw_rect.width = width + 2; - draw_rect.height = height; - - clip_rect = draw_rect; - clip_rect.height--; - } + if (start && stop) + { + /* Both edges of the notebook are covered by the item */ + element = XP_THEME_ELEMENT_TAB_ITEM_BOTH_EDGE; + } + else if (start) + { + /* The start edge is covered by the item */ + element = XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE; + } + else if (stop) + { + /* the stop edge is reached by the item */ + element = XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE; + } else - { - draw_rect.x = x + 2; - draw_rect.y = y; - draw_rect.width = width - 2; - draw_rect.height = height - 2; - clip_rect = draw_rect; - } - - /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */ - widget_right = widget->allocation.x + widget->allocation.width - border_width - 2; - - if (draw_rect.x + draw_rect.width >= widget_right) - { - draw_rect.width = clip_rect.width = widget_right - draw_rect.x; - } - } - if (gap_side == GTK_POS_BOTTOM) - { - int widget_right; - - if (state_type == GTK_STATE_NORMAL) - { - draw_rect.x = x; - draw_rect.y = y; - draw_rect.width = width + 2; - draw_rect.height = height; - - clip_rect = draw_rect; - } - else - { - draw_rect.x = x + 2; - draw_rect.y = y + 2; - draw_rect.width = width - 2; - draw_rect.height = height - 2; - clip_rect = draw_rect; - } - - /* If we are currently drawing the right-most tab, and if that tab is the selected tab... */ - widget_right = widget->allocation.x + widget->allocation.width - border_width - 2; - - if (draw_rect.x + draw_rect.width >= widget_right) - { - draw_rect.width = clip_rect.width = widget_right - draw_rect.x; - } - - rotation = GDK_PIXBUF_ROTATE_UPSIDEDOWN; - } - else if (gap_side == GTK_POS_LEFT) - { - int widget_bottom; - - if (state_type == GTK_STATE_NORMAL) - { - draw_rect.x = x; - draw_rect.y = y; - draw_rect.width = width; - draw_rect.height = height + 2; - - clip_rect = draw_rect; - clip_rect.width--; - } - else - { - draw_rect.x = x; - draw_rect.y = y + 2; - draw_rect.width = width - 2; - draw_rect.height = height - 2; - clip_rect = draw_rect; - } - - /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */ - widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2; - - if (draw_rect.y + draw_rect.height >= widget_bottom) - { - draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y; - } - - rotation = GDK_PIXBUF_ROTATE_COUNTERCLOCKWISE; - } - else if (gap_side == GTK_POS_RIGHT) - { - int widget_bottom; - - if (state_type == GTK_STATE_NORMAL) - { - draw_rect.x = x + 1; - draw_rect.y = y; - draw_rect.width = width; - draw_rect.height = height + 2; - - clip_rect = draw_rect; - clip_rect.width--; - } - else - { - draw_rect.x = x + 2; - draw_rect.y = y + 2; - draw_rect.width = width - 2; - draw_rect.height = height - 2; - clip_rect = draw_rect; - } - - /* If we are currently drawing the bottom-most tab, and if that tab is the selected tab... */ - widget_bottom = widget->allocation.x + widget->allocation.height - border_width - 2; - - if (draw_rect.y + draw_rect.height >= widget_bottom) - { - draw_rect.height = clip_rect.height = widget_bottom - draw_rect.y; - } - - rotation = GDK_PIXBUF_ROTATE_CLOCKWISE; - } - - if (gap_side == GTK_POS_TOP) - { - if (!xp_theme_draw (window, XP_THEME_ELEMENT_TAB_ITEM, style, - draw_rect.x, draw_rect.y, - draw_rect.width, draw_rect.height, - state_type, &clip_rect)) - { - return FALSE; - } + { + /* no edge should be aligned with the tab */ + element = XP_THEME_ELEMENT_TAB_ITEM; + } } else { - GdkPixbuf *pixbuf; - GdkPixbuf *rotated; - - if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT) - { - pixmap = gdk_pixmap_new (window, clip_rect.height, clip_rect.width, -1); - - if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style, - draw_rect.y - clip_rect.y, draw_rect.x - clip_rect.x, - draw_rect.height, draw_rect.width, state_type, 0)) - { - g_object_unref (pixmap); - return FALSE; - } - - pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0, - clip_rect.height, clip_rect.width); - g_object_unref (pixmap); - } - else - { - pixmap = gdk_pixmap_new (window, clip_rect.width, clip_rect.height, -1); - - if (!xp_theme_draw (pixmap, XP_THEME_ELEMENT_TAB_ITEM, style, - draw_rect.x - clip_rect.x, draw_rect.y - clip_rect.y, - draw_rect.width, draw_rect.height, state_type, 0)) - { - g_object_unref (pixmap); - return FALSE; - } - - pixbuf = gdk_pixbuf_get_from_drawable (NULL, pixmap, NULL, 0, 0, 0, 0, - clip_rect.width, clip_rect.height); - g_object_unref (pixmap); - } - - rotated = gdk_pixbuf_rotate_simple (pixbuf, rotation); - g_object_unref (pixbuf); - pixbuf = rotated; - - // XXX - This is really hacky and evil. When we're drawing the left-most tab - // while it is active on a bottom-oriented notebook, there is one white - // pixel at the top. There may be a better solution than this if someone - // has time to discover it. - if (gap_side == GTK_POS_BOTTOM && state_type == GTK_STATE_NORMAL - && x == widget->allocation.x) - { - int rowstride = gdk_pixbuf_get_rowstride (pixbuf); - int n_channels = gdk_pixbuf_get_n_channels (pixbuf); - int psub = 0; - - guchar *pixels = gdk_pixbuf_get_pixels (pixbuf); - guchar *p = pixels + rowstride; - - for (psub = 0; psub < n_channels; psub++) - { - pixels[psub] = p[psub]; - } - } - - cr = gdk_cairo_create (window); - gdk_cairo_set_source_pixbuf (cr, pixbuf, clip_rect.x, clip_rect.y); - cairo_paint (cr); - cairo_destroy (cr); - g_object_unref (pixbuf); + /* Ideally, we should do the same here. Unfortunately, we don't have ways + * to determine what tab widget is actually being drawn here, so we can't + * determine its position relative to the borders */ + element = XP_THEME_ELEMENT_TAB_ITEM; } + draw_rect.x = x; + draw_rect.y = y; + draw_rect.width = width; + draw_rect.height = height; + + /* Perform adjustments required to have the theme perfectly aligned */ + if (state_type == GTK_STATE_ACTIVE) + { + switch (gap_side) + { + case GTK_POS_TOP: + draw_rect.x += 2; + draw_rect.width -= 2; + draw_rect.height -= 1; + break; + case GTK_POS_BOTTOM: + draw_rect.x += 2; + draw_rect.width -= 2; + draw_rect.y += 1; + draw_rect.height -= 1; + break; + case GTK_POS_LEFT: + draw_rect.y += 2; + draw_rect.height -= 2; + draw_rect.width -= 1; + break; + case GTK_POS_RIGHT: + draw_rect.y += 2; + draw_rect.height -= 2; + draw_rect.x += 1; + draw_rect.width -= 1; + break; + } + } + else + { + switch (gap_side) + { + case GTK_POS_TOP: + draw_rect.height += 1; + draw_rect.width += 2; + break; + case GTK_POS_BOTTOM: + draw_rect.y -= 1; + draw_rect.height += 1; + draw_rect.width += 2; + break; + case GTK_POS_LEFT: + draw_rect.width += 1; + draw_rect.height += 2; + break; + case GTK_POS_RIGHT: + draw_rect.x -= 1; + draw_rect.width += 1; + draw_rect.height += 2; + break; + } + } + + clip_rect = draw_rect; + + /* Take care of obvious case where the clipping is an empty region */ + if (clip_rect.width <= 0 || clip_rect.height <= 0) + return TRUE; + + /* Simple case: tabs on top are just drawn as is */ + if (gap_side == GTK_POS_TOP) + { + return xp_theme_draw (window, element, style, + draw_rect.x, draw_rect.y, + draw_rect.width, draw_rect.height, + state_type, &clip_rect); + } + + /* For other cases, we need to print the tab on a pixmap, and then rotate + * it according to the gap side */ + if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT) + { + /* pixmap will have width/height inverted as we'll rotate +- PI / 2 */ + d_w = draw_rect.height; + d_h = draw_rect.width; + } + else + { + d_w = draw_rect.width; + d_h = draw_rect.height; + } + + pixmap = gdk_pixmap_new (window, d_w, d_h, -1); + + /* First copy the previously saved window background */ + cr = gdk_cairo_create (pixmap); + + /* pixmaps unfortunately don't handle the alpha channel. We then + * paint it first in white, hoping the actual background is clear */ + cairo_set_source_rgb (cr, 1, 1, 1); + cairo_paint (cr); + cairo_destroy (cr); + + if (!xp_theme_draw (pixmap, element, style, 0, 0, d_w, d_h, state_type, 0)) + { + g_object_unref (pixmap); + return FALSE; + } + + /* Now we have the pixmap, we need to flip/rotate it according to its + * final position. We'll do it using cairo on the dest window */ + cr = gdk_cairo_create (window); + cairo_rectangle (cr, clip_rect.x, clip_rect.y, + clip_rect.width, clip_rect.height); + cairo_clip (cr); + cairo_translate(cr, draw_rect.x + draw_rect.width * 0.5, + draw_rect.y + draw_rect.height * 0.5); + + if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_RIGHT) { + cairo_rotate (cr, M_PI/2.0); + } + + if (gap_side == GTK_POS_LEFT || gap_side == GTK_POS_BOTTOM) { + cairo_scale (cr, 1, -1); + } + + cairo_translate(cr, -d_w * 0.5, -d_h * 0.5); + gdk_cairo_set_source_pixmap (cr, pixmap, 0, 0); + cairo_paint (cr); + cairo_destroy (cr); + return TRUE; } @@ -2643,67 +2703,68 @@ draw_extension (GtkStyle *style, { GtkNotebook *notebook = GTK_NOTEBOOK (widget); - /* Why this differs from gap_side, I have no idea.. */ - int real_gap_side = gtk_notebook_get_tab_pos (notebook); + /* draw_themed_tab_button and draw_tab_button expect to work with tab + * position, instead of simply taking the "side of the gap" (gap_side) + * which simply said is the side of the tab that touches the notebook + * frame and is always the exact opposite of the gap side... */ + int tab_pos = gtk_notebook_get_tab_pos (notebook); if (!draw_themed_tab_button (style, window, state_type, - GTK_NOTEBOOK (widget), x, y, - width, height, real_gap_side)) + notebook, x, y, + width, height, tab_pos)) { if (!draw_tab_button (style, window, state_type, shadow_type, area, widget, - detail, x, y, width, height, real_gap_side)) + detail, x, y, width, height, tab_pos)) { + /* GtkStyle expects the usual gap_side */ parent_class->draw_extension (style, window, state_type, shadow_type, area, widget, detail, x, y, width, height, - real_gap_side); + gap_side); } } } } static void -draw_box_gap (GtkStyle *style, GdkWindow *window, GtkStateType state_type, - GtkShadowType shadow_type, GdkRectangle *area, - GtkWidget *widget, const gchar *detail, gint x, - gint y, gint width, gint height, GtkPositionType gap_side, - gint gap_x, gint gap_width) +draw_box_gap (GtkStyle *style, + GdkWindow *window, + GtkStateType state_type, + GtkShadowType shadow_type, + GdkRectangle *area, + GtkWidget *widget, + const gchar *detail, + gint x, + gint y, + gint width, + gint height, + GtkPositionType gap_side, + gint gap_x, + gint gap_width) { if (GTK_IS_NOTEBOOK (widget) && detail && !strcmp (detail, "notebook")) { GtkNotebook *notebook = GTK_NOTEBOOK (widget); - int side = gtk_notebook_get_tab_pos (notebook); - int x2 = x, y2 = y, w2 = width, h2 = height; - if (side == GTK_POS_TOP) - { - x2 = x; - y2 = y - gtk_notebook_get_tab_vborder (notebook); - w2 = width; - h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2; - } - else if (side == GTK_POS_BOTTOM) - { - x2 = x; - y2 = y; - w2 = width; - h2 = height + gtk_notebook_get_tab_vborder (notebook) * 2; - } - else if (side == GTK_POS_LEFT) - { - x2 = x - gtk_notebook_get_tab_hborder (notebook); - y2 = y; - w2 = width + gtk_notebook_get_tab_hborder (notebook); - h2 = height; - } - else if (side == GTK_POS_RIGHT) - { - x2 = x; - y2 = y; - w2 = width + gtk_notebook_get_tab_hborder (notebook) * 2; - h2 = height; - } + int side = gtk_notebook_get_tab_pos (notebook); + int x2 = x, y2 = y; + int w2 = width + style->xthickness, h2 = height + style->ythickness; + + switch (side) + { + case GTK_POS_TOP: + y2 -= 1; + break; + case GTK_POS_BOTTOM: + break; + case GTK_POS_LEFT: + x2 -= 1; + break; + case GTK_POS_RIGHT: + w2 += 1; + break; + } if (xp_theme_draw (window, XP_THEME_ELEMENT_TAB_PANE, style, x2, y2, w2, h2, state_type, area)) diff --git a/modules/engines/ms-windows/xp_theme.c b/modules/engines/ms-windows/xp_theme.c index bdd4240238..3d07891d6c 100755 --- a/modules/engines/ms-windows/xp_theme.c +++ b/modules/engines/ms-windows/xp_theme.c @@ -121,6 +121,7 @@ static const short element_part_map[XP_THEME_ELEMENT__SIZEOF] = { TABP_TABITEM, TABP_TABITEMLEFTEDGE, TABP_TABITEMRIGHTEDGE, + TABP_TABITEMBOTHEDGE, TABP_PANE, SBP_THUMBBTNHORZ, SBP_THUMBBTNVERT, @@ -408,6 +409,7 @@ xp_theme_get_handle_by_element (XpThemeElement element) case XP_THEME_ELEMENT_TAB_ITEM: case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE: case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE: + case XP_THEME_ELEMENT_TAB_ITEM_BOTH_EDGE: case XP_THEME_ELEMENT_TAB_PANE: klazz = XP_THEME_CLASS_TAB; break; @@ -536,6 +538,7 @@ xp_theme_map_gtk_state (XpThemeElement element, GtkStateType state) case XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE: case XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE: + case XP_THEME_ELEMENT_TAB_ITEM_BOTH_EDGE: case XP_THEME_ELEMENT_TAB_ITEM: switch (state) { @@ -940,6 +943,7 @@ xp_theme_draw (GdkWindow *win, XpThemeElement element, GtkStyle *style, HDC dc; XpDCInfo dc_info; int part_state; + HWND hwnd; if (!xp_theme_is_drawable (element)) return FALSE; @@ -949,8 +953,9 @@ xp_theme_draw (GdkWindow *win, XpThemeElement element, GtkStyle *style, return FALSE; /* FIXME: Recheck its function */ - if (GDK_IS_WINDOW (win) && gdk_win32_window_is_win32 (win)) - enable_theme_dialog_texture_func (GDK_WINDOW_HWND (win), ETDT_ENABLETAB); + hwnd = gdk_win32_window_get_impl_hwnd (win); + if (hwnd != NULL) + enable_theme_dialog_texture_func (hwnd, ETDT_ENABLETAB); dc = get_window_dc (style, win, state_type, &dc_info, x, y, width, height, @@ -976,7 +981,7 @@ xp_theme_draw (GdkWindow *win, XpThemeElement element, GtkStyle *style, /* Support transparency */ if (is_theme_partially_transparent_func (theme, element_part_map[element], part_state)) - draw_theme_parent_background_func (GDK_WINDOW_HWND (win), dc, pClip); + draw_theme_parent_background_func (hwnd, dc, pClip); draw_theme_background_func (theme, dc, element_part_map[element], part_state, &rect, pClip); diff --git a/modules/engines/ms-windows/xp_theme.h b/modules/engines/ms-windows/xp_theme.h index dfacb434cc..33a56b33e0 100755 --- a/modules/engines/ms-windows/xp_theme.h +++ b/modules/engines/ms-windows/xp_theme.h @@ -59,6 +59,7 @@ typedef enum XP_THEME_ELEMENT_TAB_ITEM, XP_THEME_ELEMENT_TAB_ITEM_LEFT_EDGE, XP_THEME_ELEMENT_TAB_ITEM_RIGHT_EDGE, + XP_THEME_ELEMENT_TAB_ITEM_BOTH_EDGE, XP_THEME_ELEMENT_TAB_PANE, XP_THEME_ELEMENT_SCROLLBAR_H, XP_THEME_ELEMENT_SCROLLBAR_V, diff --git a/tests/print-editor.c b/tests/print-editor.c index b476e013cd..7757626a87 100644 --- a/tests/print-editor.c +++ b/tests/print-editor.c @@ -436,6 +436,7 @@ typedef struct GtkWidget *spin; GtkWidget *area; gint page; + GtkPrintContext *context; PrintData *data; gdouble dpi_x, dpi_y; } PreviewOp; @@ -446,6 +447,11 @@ preview_expose (GtkWidget *widget, gpointer data) { PreviewOp *pop = data; + cairo_t *cr; + + cr = gdk_cairo_create (pop->area->window); + gtk_print_context_set_cairo_context (pop->context, cr, pop->dpi_x, pop->dpi_y); + cairo_destroy (cr); gdk_window_clear (pop->area->window); gtk_print_operation_preview_render_page (pop->preview, @@ -567,8 +573,6 @@ preview_cb (GtkPrintOperation *op, gtk_widget_set_size_request (GTK_WIDGET (da), width, height); gtk_box_pack_start (GTK_BOX (vbox), da, TRUE, TRUE, 0); - gtk_widget_set_double_buffered (da, FALSE); - gtk_widget_realize (da); cr = gdk_cairo_create (da->window); @@ -582,6 +586,7 @@ preview_cb (GtkPrintOperation *op, pop->spin = page; pop->area = da; pop->page = 1; + pop->context = context; g_signal_connect (page, "value-changed", G_CALLBACK (update_page), pop);