* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
gint *y);
+static void
+gdk_quartz_ns_notification_callback (CFNotificationCenterRef center,
+ void *observer,
+ CFStringRef name,
+ const void *object,
+ CFDictionaryRef userInfo)
+{
+ GdkEvent new_event;
+
+ new_event.type = GDK_SETTING;
+ new_event.setting.window = gdk_screen_get_root_window (_gdk_screen);
+ new_event.setting.send_event = FALSE;
+ new_event.setting.action = GDK_SETTING_ACTION_CHANGED;
+ new_event.setting.name = NULL;
+
+ /* Translate name */
+ if (CFStringCompare (name,
+ CFSTR("AppleNoRedisplayAppearancePreferenceChanged"),
+ 0) == kCFCompareEqualTo)
+ new_event.setting.name = "gtk-primary-button-warps-slider";
+
+ if (!new_event.setting.name)
+ return;
+
+ gdk_event_put (&new_event);
+}
+
+static void
+gdk_quartz_events_init_notifications (void)
+{
+ static gboolean notifications_initialized = FALSE;
+
+ if (notifications_initialized)
+ return;
+ notifications_initialized = TRUE;
+
+ /* Initialize any handlers for notifications we want to push to GTK
+ * through GdkEventSettings.
+ */
+
+ /* This is an undocumented *distributed* notification to listen for changes
+ * in scrollbar jump behavior. It is used by LibreOffice and WebKit as well.
+ */
+ CFNotificationCenterAddObserver (CFNotificationCenterGetDistributedCenter (),
+ NULL,
+ &gdk_quartz_ns_notification_callback,
+ CFSTR ("AppleNoRedisplayAppearancePreferenceChanged"),
+ NULL,
+ CFNotificationSuspensionBehaviorDeliverImmediately);
+}
+
void
_gdk_quartz_events_init (void)
{
_gdk_quartz_event_loop_init ();
+ gdk_quartz_events_init_notifications ();
current_keyboard_window = g_object_ref (_gdk_root);
}
(_gdk_quartz_event_loop_check_pending ()));
}
-static void
-break_all_grabs (guint32 time)
+void
+_gdk_quartz_events_break_all_grabs (guint32 time)
{
GList *list, *l;
GdkDeviceManager *device_manager;
get_time_from_ns_event (NSEvent *event)
{
double time = [event timestamp];
-
- return time * 1000.0;
+
+ /* cast via double->uint64 conversion to make sure that it is
+ * wrapped on 32-bit machines when it overflows
+ */
+ return (guint32) (guint64) (time * 1000.0);
}
static int
{
GdkEventType type;
gint state;
- gint button;
- state = get_keyboard_modifiers_from_ns_event (nsevent);
+ state = get_keyboard_modifiers_from_ns_event (nsevent) |
+ _gdk_quartz_events_get_current_mouse_modifiers ();
switch ([nsevent type])
{
case NSRightMouseDown:
case NSOtherMouseDown:
type = GDK_BUTTON_PRESS;
+ state &= ~get_mouse_button_modifiers_from_ns_event (nsevent);
break;
+
case NSLeftMouseUp:
case NSRightMouseUp:
case NSOtherMouseUp:
type = GDK_BUTTON_RELEASE;
state |= get_mouse_button_modifiers_from_ns_event (nsevent);
break;
+
default:
g_assert_not_reached ();
}
-
- button = get_mouse_button_from_ns_event (nsevent);
event->any.type = type;
event->button.window = window;
event->button.y_root = y_root;
/* FIXME event->axes */
event->button.state = state;
- event->button.button = button;
+ event->button.button = get_mouse_button_from_ns_event (nsevent);
event->button.device = _gdk_display->core_pointer;
}
gint x_root,
gint y_root)
{
- GdkModifierType state;
-
- state = get_keyboard_modifiers_from_ns_event (nsevent);
-
- switch ([nsevent type])
- {
- case NSLeftMouseDragged:
- case NSRightMouseDragged:
- case NSOtherMouseDragged:
- state |= get_mouse_button_modifiers_from_ns_event (nsevent);
- break;
-
- case NSMouseMoved:
- break;
- }
-
event->any.type = GDK_MOTION_NOTIFY;
event->motion.window = window;
event->motion.time = get_time_from_ns_event (nsevent);
event->motion.x_root = x_root;
event->motion.y_root = y_root;
/* FIXME event->axes */
- event->motion.state = state;
+ event->motion.state = get_keyboard_modifiers_from_ns_event (nsevent) |
+ _gdk_quartz_events_get_current_mouse_modifiers ();
event->motion.is_hint = FALSE;
event->motion.device = _gdk_display->core_pointer;
}
gint y,
gint x_root,
gint y_root,
+ gdouble delta_x,
+ gdouble delta_y,
GdkScrollDirection direction)
{
NSPoint point;
event->scroll.state = get_keyboard_modifiers_from_ns_event (nsevent);
event->scroll.direction = direction;
event->scroll.device = _gdk_display->core_pointer;
+ event->scroll.delta_x = delta_x;
+ event->scroll.delta_y = delta_y;
}
static void
event->key.state |= _gdk_quartz_events_get_current_mouse_modifiers ();
+ /* The X11 backend adds the first virtual modifier MOD2..MOD5 are
+ * mapped to. Since we only have one virtual modifier in the quartz
+ * backend, calling the standard function will do.
+ */
+ gdk_keymap_add_virtual_modifiers (gdk_keymap_get_for_display (_gdk_display),
+ &event->key.state);
+
event->key.string = NULL;
/* Fill in ->string since apps depend on it, taken from the x11 backend. */
GdkWindowImplQuartz *toplevel_impl;
gboolean lion;
- /* Resizing only begins if an NSLeftMouseButton event is received in
- * the resizing area. Handle anything else.
+ /* Resizing from the resize indicator only begins if an NSLeftMouseButton
+ * event is received in the resizing area.
*/
- if ([event type] != NSLeftMouseDown)
- return FALSE;
-
toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
if ([toplevel_impl->toplevel showsResizeIndicator])
+ if ([event type] == NSLeftMouseDown &&
+ [toplevel_impl->toplevel showsResizeIndicator])
{
NSRect frame;
* the selector isRestorable to see if we're on 10.7.
* This extra check is in case the user starts
* dragging before GDK recognizes the grab.
+ *
+ * We perform this check for a button press of all buttons, because we
+ * do receive, for instance, a right mouse down event for a GDK window
+ * for x-coordinate range [-3, 0], but we do not want to forward this
+ * into GDK. Forwarding such events into GDK will confuse the pointer
+ * window finding code, because there are no GdkWindows present in
+ * the range [-3, 0].
*/
lion = gdk_quartz_osx_version () >= GDK_OSX_LION;
- if (lion && (x < GDK_LION_RESIZE ||
- x > toplevel->width - GDK_LION_RESIZE ||
- y > toplevel->height - GDK_LION_RESIZE))
- return TRUE;
+ if (lion &&
+ ([event type] == NSLeftMouseDown ||
+ [event type] == NSRightMouseDown ||
+ [event type] == NSOtherMouseDown))
+ {
+ if (x < GDK_LION_RESIZE ||
+ x > toplevel->width - GDK_LION_RESIZE ||
+ y > toplevel->height - GDK_LION_RESIZE)
+ return TRUE;
+ }
return FALSE;
}
if (event_type == NSAppKitDefined)
{
if ([nsevent subtype] == NSApplicationDeactivatedEventType)
- break_all_grabs (get_time_from_ns_event (nsevent));
+ _gdk_quartz_events_break_all_grabs (get_time_from_ns_event (nsevent));
/* This could potentially be used to break grabs when clicking
* on the title. The subtype 20 is undocumented so it's probably
*/
if ([(GdkQuartzNSWindow *)nswindow isInMove])
{
- break_all_grabs (get_time_from_ns_event (nsevent));
+ _gdk_quartz_events_break_all_grabs (get_time_from_ns_event (nsevent));
return FALSE;
}
+ /* Also when in a manual resize, we ignore events so that these are
+ * pushed to GdkQuartzWindow's sendEvent handler.
+ */
+ if ([(GdkQuartzWindow *)nswindow isInManualResize])
+ return FALSE;
+
/* Find the right GDK window to send the event to, taking grabs and
* event masks into consideration.
*/
case NSScrollWheel:
{
- float dx = [nsevent deltaX];
- float dy = [nsevent deltaY];
- GdkScrollDirection direction;
+ GdkScrollDirection direction;
+ float dx;
+ float dy;
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+ if (gdk_quartz_osx_version() >= GDK_OSX_LION &&
+ [nsevent hasPreciseScrollingDeltas])
+ {
+ dx = [nsevent scrollingDeltaX];
+ dy = [nsevent scrollingDeltaY];
+ direction = GDK_SCROLL_SMOOTH;
- if (dy != 0)
+ fill_scroll_event (window, event, nsevent, x, y, x_root, y_root,
+ -dx, -dy, direction);
+
+ /* Fall through for scroll buttons emulation */
+ }
+#endif
+ dx = [nsevent deltaX];
+ dy = [nsevent deltaY];
+
+ if (dy != 0.0)
{
if (dy < 0.0)
direction = GDK_SCROLL_DOWN;
else
direction = GDK_SCROLL_UP;
- fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
+ dy = fabs (dy);
+ dx = 0.0;
}
-
- if (dx != 0)
+ else if (dx != 0.0)
{
if (dx < 0.0)
direction = GDK_SCROLL_RIGHT;
else
direction = GDK_SCROLL_LEFT;
- fill_scroll_event (window, event, nsevent, x, y, x_root, y_root, direction);
+ dx = fabs (dx);
+ dy = 0.0;
+ }
+
+ if (dx != 0.0 || dy != 0.0)
+ {
+#ifdef AVAILABLE_MAC_OS_X_VERSION_10_7_AND_LATER
+ if (gdk_quartz_osx_version() >= GDK_OSX_LION &[nsevent hasPreciseScrollingDeltas])
+ {
+ GdkEvent *emulated_event;
+
+ emulated_event = gdk_event_new (GDK_SCROLL);
+ _gdk_event_set_pointer_emulated (emulated_event, TRUE);
+ fill_scroll_event (window, emulated_event, nsevent,
+ x, y, x_root, y_root,
+ dx, dy, direction);
+ append_event (emulated_event, TRUE);
+ }
+ else
+#endif
+ fill_scroll_event (window, event, nsevent,
+ x, y, x_root, y_root,
+ dx, dy, direction);
}
}
break;
g_list_free_1 (node);
gdk_event_free (event);
- GDK_THREADS_LEAVE ();
+ gdk_threads_leave ();
[NSApp sendEvent:nsevent];
- GDK_THREADS_ENTER ();
+ gdk_threads_enter ();
}
_gdk_quartz_event_loop_release_event (nsevent);
GDK_QUARTZ_RELEASE_POOL;
+ return TRUE;
+ }
+ else if (strcmp (name, "gtk-primary-button-warps-slider") == 0)
+ {
+ GDK_QUARTZ_ALLOC_POOL;
+
+ BOOL setting = [[NSUserDefaults standardUserDefaults] boolForKey:@"AppleScrollerPagingBehavior"];
+
+ /* If the Apple property is YES, it means "warp" */
+ g_value_set_boolean (value, setting == YES);
+
+ GDK_QUARTZ_RELEASE_POOL;
+
return TRUE;
}