* 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"
/* This is the window corresponding to the key window */
static GdkWindow *current_keyboard_window;
-/* This is the event mask and button state from the last event */
-static GdkModifierType current_keyboard_modifiers;
-static GdkModifierType current_button_state;
static void append_event (GdkEvent *event,
gboolean windowing);
+static GdkWindow *find_toplevel_under_pointer (GdkDisplay *display,
+ NSPoint screen_point,
+ gint *x,
+ gint *y);
+
+
void
_gdk_quartz_events_init (void)
{
}
}
+static GdkModifierType
+get_mouse_button_modifiers_from_ns_buttons (NSUInteger nsbuttons)
+{
+ GdkModifierType modifiers = 0;
+
+ if (nsbuttons & (1 << 0))
+ modifiers |= GDK_BUTTON1_MASK;
+ if (nsbuttons & (1 << 1))
+ modifiers |= GDK_BUTTON3_MASK;
+ if (nsbuttons & (1 << 2))
+ modifiers |= GDK_BUTTON2_MASK;
+ if (nsbuttons & (1 << 3))
+ modifiers |= GDK_BUTTON4_MASK;
+ if (nsbuttons & (1 << 4))
+ modifiers |= GDK_BUTTON5_MASK;
+
+ return modifiers;
+}
+
static GdkModifierType
get_mouse_button_modifiers_from_ns_event (NSEvent *event)
{
}
static GdkModifierType
-get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
+get_keyboard_modifiers_from_ns_flags (NSUInteger nsflags)
{
GdkModifierType modifiers = 0;
- int nsflags;
- nsflags = [nsevent modifierFlags];
-
if (nsflags & NSAlphaShiftKeyMask)
modifiers |= GDK_LOCK_MASK;
if (nsflags & NSShiftKeyMask)
return modifiers;
}
+static GdkModifierType
+get_keyboard_modifiers_from_ns_event (NSEvent *nsevent)
+{
+ return get_keyboard_modifiers_from_ns_flags ([nsevent modifierFlags]);
+}
+
/* Return an event mask from an NSEvent */
static GdkEventMask
get_event_mask_from_ns_event (NSEvent *nsevent)
gint *x,
gint *y)
{
- GdkQuartzView *view;
GdkWindow *toplevel;
- NSPoint point;
- view = (GdkQuartzView *)[[nsevent window] contentView];
+ if ([nsevent window])
+ {
+ GdkQuartzView *view;
+ NSPoint point;
- toplevel = [view gdkWindow];
+ view = (GdkQuartzView *)[[nsevent window] contentView];
- point = [nsevent locationInWindow];
- *screen_point = [[nsevent window] convertBaseToScreen:point];
+ toplevel = [view gdkWindow];
- *x = point.x;
- *y = toplevel->height - point.y;
+ point = [nsevent locationInWindow];
+ *screen_point = [[nsevent window] convertBaseToScreen:point];
+
+ *x = point.x;
+ *y = toplevel->height - point.y;
+ }
+ else
+ {
+ /* Fallback used when no NSWindow set. This happens e.g. when
+ * we allow motion events without a window set in gdk_event_translate()
+ * that occur immediately after the main menu bar was clicked/used.
+ */
+ *screen_point = [NSEvent mouseLocation];
+ toplevel = find_toplevel_under_pointer (_gdk_display,
+ *screen_point,
+ x, y);
+ }
return toplevel;
}
event->motion.x_root = x_root;
event->motion.y_root = y_root;
/* FIXME event->axes */
- event->motion.state = 0;
+ event->motion.state = _gdk_quartz_events_get_current_keyboard_modifiers () |
+ _gdk_quartz_events_get_current_mouse_modifiers ();
event->motion.is_hint = FALSE;
event->motion.device = _gdk_display->core_pointer;
event->crossing.y_root = y_root;
event->crossing.mode = GDK_CROSSING_NORMAL;
event->crossing.detail = GDK_NOTIFY_ANCESTOR;
- event->crossing.state = 0;
+ event->crossing.state = _gdk_quartz_events_get_current_keyboard_modifiers () |
+ _gdk_quartz_events_get_current_mouse_modifiers ();
gdk_event_set_device (event, _gdk_display->core_pointer);
gint *x,
gint *y)
{
- NSPoint point;
NSPoint screen_point;
NSEventType event_type;
GdkWindow *toplevel;
- GdkQuartzView *view;
GdkDisplay *display;
GdkDeviceGrabInfo *grab;
- view = (GdkQuartzView *)[[nsevent window] contentView];
- toplevel = [view gdkWindow];
+ toplevel = get_toplevel_from_ns_event (nsevent, &screen_point, x, y);
display = gdk_window_get_display (toplevel);
event_type = [nsevent type];
- point = [nsevent locationInWindow];
- screen_point = [[nsevent window] convertBaseToScreen:point];
/* From the docs for XGrabPointer:
*
event->crossing.y_root = y_root;
event->crossing.mode = mode;
event->crossing.detail = detail;
- event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent);
+ event->crossing.state = get_keyboard_modifiers_from_ns_event (nsevent) |
+ _gdk_quartz_events_get_current_mouse_modifiers ();
gdk_event_set_device (event, _gdk_display->core_pointer);
{
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;
}
event->key.state |= mask;
}
- event->key.state |= current_button_state;
+ 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;
GdkModifierType
_gdk_quartz_events_get_current_keyboard_modifiers (void)
{
- return current_keyboard_modifiers;
+ if (gdk_quartz_osx_version () >= GDK_OSX_SNOW_LEOPARD)
+ {
+ return get_keyboard_modifiers_from_ns_flags ([NSClassFromString(@"NSEvent") modifierFlags]);
+ }
+ else
+ {
+ guint carbon_modifiers = GetCurrentKeyModifiers ();
+ GdkModifierType modifiers = 0;
+
+ if (carbon_modifiers & alphaLock)
+ modifiers |= GDK_LOCK_MASK;
+ if (carbon_modifiers & shiftKey)
+ modifiers |= GDK_SHIFT_MASK;
+ if (carbon_modifiers & controlKey)
+ modifiers |= GDK_CONTROL_MASK;
+ if (carbon_modifiers & optionKey)
+ modifiers |= GDK_MOD1_MASK;
+ if (carbon_modifiers & cmdKey)
+ modifiers |= GDK_MOD2_MASK;
+
+ return modifiers;
+ }
}
GdkModifierType
_gdk_quartz_events_get_current_mouse_modifiers (void)
{
- return current_button_state;
+ if (gdk_quartz_osx_version () >= GDK_OSX_SNOW_LEOPARD)
+ {
+ return get_mouse_button_modifiers_from_ns_buttons ([NSClassFromString(@"NSEvent") pressedMouseButtons]);
+ }
+ else
+ {
+ return get_mouse_button_modifiers_from_ns_buttons (GetCurrentButtonState ());
+ }
}
/* Detect window resizing */
{
GdkWindowImplQuartz *toplevel_impl;
gboolean lion;
+
/* Resizing only begins if an NSLeftMouseButton event is received in
* the resizing area. Handle anything else.
*/
if ([event type] != NSLeftMouseDown)
- return FALSE;
+ return FALSE;
toplevel_impl = (GdkWindowImplQuartz *)toplevel->impl;
if ([toplevel_impl->toplevel showsResizeIndicator])
* is too important to not make functional.
*/
frame = [toplevel_impl->view bounds];
- if (x > frame.size.width - GRIP_WIDTH
- && x < frame.size.width
- && y > frame.size.height - GRIP_HEIGHT
- && y < frame.size.height)
- {
- return TRUE;
- }
+ if (x > frame.size.width - GRIP_WIDTH &&
+ x < frame.size.width &&
+ y > frame.size.height - GRIP_HEIGHT &&
+ y < frame.size.height)
+ return TRUE;
}
+
/* If we're on Lion and within 5 pixels of an edge,
* then assume that the user wants to resize, and
* return NULL to let Quartz get on with it. We check
* This extra check is in case the user starts
* dragging before GDK recognizes the grab.
*/
-
- lion = gdk_quartz_osx_version() >= GDK_OSX_LION;
+ 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;
- }
+ x > toplevel->width - GDK_LION_RESIZE ||
+ y > toplevel->height - GDK_LION_RESIZE))
+ return TRUE;
+
return FALSE;
}
return FALSE;
}
- /* Keep track of button state, since we don't get that information
- * for key events.
- */
- switch (event_type)
- {
- case NSLeftMouseDown:
- case NSRightMouseDown:
- case NSOtherMouseDown:
- current_button_state |= get_mouse_button_modifiers_from_ns_event (nsevent);
- break;
- case NSLeftMouseUp:
- case NSRightMouseUp:
- case NSOtherMouseUp:
- current_button_state &= ~get_mouse_button_modifiers_from_ns_event (nsevent);
- break;
- default:
- break;
- }
-
if (_gdk_default_filters)
{
/* Apply global filters */
nswindow = [nsevent window];
- /* Ignore events for no window or ones not created by GDK. */
- if (!nswindow || ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
+ /* Ignore events for windows not created by GDK. */
+ if (nswindow && ![[nswindow contentView] isKindOfClass:[GdkQuartzView class]])
return FALSE;
+ /* Ignore events for ones with no windows */
+ if (!nswindow)
+ {
+ GdkWindow *toplevel = NULL;
+
+ if (event_type == NSMouseMoved)
+ {
+ /* Motion events received after clicking the menu bar do not have the
+ * window field set. Instead of giving up on the event immediately,
+ * we first check whether this event is within our window bounds.
+ */
+ NSPoint screen_point = [NSEvent mouseLocation];
+ gint x_tmp, y_tmp;
+
+ toplevel = find_toplevel_under_pointer (_gdk_display,
+ screen_point,
+ &x_tmp, &y_tmp);
+ }
+
+ if (!toplevel)
+ return FALSE;
+ }
+
/* Ignore events and break grabs while the window is being
* dragged. This is a workaround for the window getting events for
* the window title.
window = find_window_for_ns_event (nsevent, &x, &y, &x_root, &y_root);
if (!window)
return FALSE;
+
/* Quartz handles resizing on its own, so we want to stay out of the way. */
- if (test_resize(nsevent, window, x, y))
+ if (test_resize (nsevent, window, x, y))
return FALSE;
/* Apply any window filters. */
}
}
- current_keyboard_modifiers = get_keyboard_modifiers_from_ns_event (nsevent);
-
return_val = TRUE;
switch (event_type)