Compare commits
	
		
			17 Commits
		
	
	
		
			benzea/ci-
			...
			wip/waylan
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 531a7b2812 | ||
|   | 580669cdea | ||
|   | e50a578ad3 | ||
|   | 06b3d36e97 | ||
|   | 715fa91599 | ||
|   | 997188e914 | ||
|   | c6dd56f9ce | ||
|   | 466af03ed3 | ||
|   | 9c2d806556 | ||
|   | 13a7c8da85 | ||
|   | d69d566087 | ||
|   | b722274886 | ||
|   | 164cdabb21 | ||
|   | 0b025f0e9c | ||
|   | 87354bdac6 | ||
|   | 02e163882a | ||
|   | 9db02a7379 | 
| @@ -366,11 +366,25 @@ meta_barrier_fire_event (MetaBarrier    *barrier, | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_display_process_barrier_event (MetaDisplay    *display, | ||||
|                                     XIBarrierEvent *xev) | ||||
| meta_display_process_barrier_event (MetaDisplay *display, | ||||
|                                     XIEvent     *event) | ||||
| { | ||||
|   MetaBarrier *barrier; | ||||
|   XIBarrierEvent *xev; | ||||
|  | ||||
|   if (event == NULL) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (event->evtype) | ||||
|     { | ||||
|     case XI_BarrierHit: | ||||
|     case XI_BarrierLeave: | ||||
|       break; | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   xev = (XIBarrierEvent *) event; | ||||
|   barrier = g_hash_table_lookup (display->xids, &xev->barrier); | ||||
|   if (barrier != NULL) | ||||
|     { | ||||
|   | ||||
| @@ -39,6 +39,7 @@ | ||||
| #include "keybindings-private.h" | ||||
| #include <meta/prefs.h> | ||||
| #include <meta/barrier.h> | ||||
| #include <clutter/clutter.h> | ||||
|  | ||||
| #ifdef HAVE_STARTUP_NOTIFICATION | ||||
| #include <libsn/sn.h> | ||||
| @@ -189,7 +190,7 @@ struct _MetaDisplay | ||||
|   MetaWindow* autoraise_window; | ||||
|  | ||||
|   /* Alt+click button grabs */ | ||||
|   unsigned int window_grab_modifiers; | ||||
|   ClutterModifierType window_grab_modifiers; | ||||
|    | ||||
|   /* current window operation */ | ||||
|   MetaGrabOp  grab_op; | ||||
| @@ -473,21 +474,23 @@ void meta_display_queue_autoraise_callback  (MetaDisplay *display, | ||||
| void meta_display_remove_autoraise_callback (MetaDisplay *display); | ||||
|  | ||||
| void meta_display_overlay_key_activate (MetaDisplay *display); | ||||
| void meta_display_accelerator_activate (MetaDisplay *display, | ||||
|                                         guint        action, | ||||
|                                         guint        deviceid, | ||||
|                                         guint        timestamp); | ||||
| void meta_display_accelerator_activate (MetaDisplay     *display, | ||||
|                                         guint            action, | ||||
|                                         ClutterKeyEvent *event); | ||||
| gboolean meta_display_modifiers_accelerator_activate (MetaDisplay *display); | ||||
|  | ||||
| /* In above-tab-keycode.c */ | ||||
| guint meta_display_get_above_tab_keycode (MetaDisplay *display); | ||||
|  | ||||
| gboolean meta_display_handle_event (MetaDisplay *display, | ||||
|                                     XEvent      *event); | ||||
| gboolean meta_display_handle_xevent (MetaDisplay *display, | ||||
|                                      XEvent      *event); | ||||
|  | ||||
| gboolean meta_display_handle_event (MetaDisplay        *display, | ||||
|                                     const ClutterEvent *event); | ||||
|  | ||||
| #ifdef HAVE_XI23 | ||||
| gboolean meta_display_process_barrier_event (MetaDisplay    *display, | ||||
|                                              XIBarrierEvent *event); | ||||
| gboolean meta_display_process_barrier_event (MetaDisplay *display, | ||||
|                                              XIEvent     *event); | ||||
| #endif /* HAVE_XI23 */ | ||||
|  | ||||
| void meta_display_set_input_focus_xwindow (MetaDisplay   *display, | ||||
|   | ||||
							
								
								
									
										2178
									
								
								src/core/display.c
									
									
									
									
									
								
							
							
						
						
									
										2178
									
								
								src/core/display.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -66,9 +66,9 @@ gboolean meta_window_grab_all_keys          (MetaWindow  *window, | ||||
|                                              guint32      timestamp); | ||||
| void     meta_window_ungrab_all_keys        (MetaWindow  *window, | ||||
|                                              guint32      timestamp); | ||||
| gboolean meta_display_process_key_event     (MetaDisplay   *display, | ||||
|                                              MetaWindow    *window, | ||||
|                                              XIDeviceEvent *event); | ||||
| gboolean meta_display_process_key_event     (MetaDisplay     *display, | ||||
|                                              MetaWindow      *window, | ||||
|                                              ClutterKeyEvent *event); | ||||
| void     meta_display_process_mapping_event (MetaDisplay *display, | ||||
|                                              XEvent      *event); | ||||
|  | ||||
| @@ -81,7 +81,3 @@ gboolean meta_prefs_remove_keybinding       (const char    *name); | ||||
|  | ||||
|  | ||||
| #endif | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -44,6 +44,7 @@ | ||||
| #include <X11/Xutil.h> | ||||
| #include <cairo.h> | ||||
| #include <gdk-pixbuf/gdk-pixbuf.h> | ||||
| #include <clutter/clutter.h> | ||||
| #include "meta-wayland-types.h" | ||||
|  | ||||
| typedef struct _MetaWindowQueue MetaWindowQueue; | ||||
| @@ -642,8 +643,8 @@ void meta_window_update_sync_request_counter (MetaWindow *window, | ||||
|                                               gint64      new_counter_value); | ||||
| #endif /* HAVE_XSYNC */ | ||||
|  | ||||
| void meta_window_handle_mouse_grab_op_event (MetaWindow *window, | ||||
|                                              XIDeviceEvent *xev); | ||||
| void meta_window_handle_mouse_grab_op_event (MetaWindow         *window, | ||||
|                                              const ClutterEvent *event); | ||||
|  | ||||
| GList* meta_window_get_workspaces (MetaWindow *window); | ||||
|  | ||||
| @@ -733,4 +734,9 @@ void meta_window_set_gtk_dbus_properties  (MetaWindow *window, | ||||
| void meta_window_set_transient_for        (MetaWindow *window, | ||||
|                                            MetaWindow *parent); | ||||
|  | ||||
| void meta_window_handle_enter (MetaWindow  *window, | ||||
|                                guint32      timestamp, | ||||
|                                guint        root_x, | ||||
|                                guint        root_y); | ||||
|  | ||||
| #endif | ||||
|   | ||||
| @@ -63,6 +63,7 @@ | ||||
| #include <X11/extensions/Xcomposite.h> | ||||
|  | ||||
| #include "meta-wayland-private.h" | ||||
| #include "meta/compositor-mutter.h" | ||||
|  | ||||
| /* Windows that unmaximize to a size bigger than that fraction of the workarea | ||||
|  * will be scaled down to that size (while maintaining aspect ratio). | ||||
| @@ -2001,6 +2002,8 @@ meta_window_unmanage (MetaWindow  *window, | ||||
|   meta_window_ungrab_keys (window); | ||||
|   meta_display_ungrab_window_buttons (window->display, window->xwindow); | ||||
|   meta_display_ungrab_focus_window_button (window->display, window); | ||||
|   if (window->display->autoraise_window == window) | ||||
|     meta_display_remove_autoraise_callback (window->display); | ||||
|  | ||||
|   if (window->client_type == META_WINDOW_CLIENT_TYPE_X11) | ||||
|     { | ||||
| @@ -9901,96 +9904,20 @@ update_resize (MetaWindow *window, | ||||
|     g_get_current_time (&window->display->grab_last_moveresize_time); | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   Window  window; | ||||
|   int     count; | ||||
|   guint32 last_time; | ||||
| } EventScannerData; | ||||
|  | ||||
| static Bool | ||||
| find_last_time_predicate (Display  *display, | ||||
|                           XEvent   *ev, | ||||
|                           XPointer  arg) | ||||
| { | ||||
|   EventScannerData *esd = (void*) arg; | ||||
|   XIEvent *xev; | ||||
|  | ||||
|   if (ev->type != GenericEvent) | ||||
|     return False; | ||||
|  | ||||
|   /* We are peeking into events not yet handled by GDK, | ||||
|    * Allocate cookie events here so we can handle XI2. | ||||
|    * | ||||
|    * GDK will handle later these events, and eventually | ||||
|    * free the cookie data itself. | ||||
|    */ | ||||
|   XGetEventData (display, &ev->xcookie); | ||||
|   xev = (XIEvent *) ev->xcookie.data; | ||||
|  | ||||
|   if (xev->evtype != XI_Motion) | ||||
|     return False; | ||||
|  | ||||
|   if (esd->window != ((XIDeviceEvent *) xev)->event) | ||||
|     return False; | ||||
|  | ||||
|   esd->count += 1; | ||||
|   esd->last_time = xev->time; | ||||
|  | ||||
|   return False; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| check_use_this_motion_notify (MetaWindow *window, | ||||
|                               XIDeviceEvent *xev) | ||||
| check_use_this_motion_notify (MetaWindow         *window, | ||||
|                               const ClutterEvent *event) | ||||
| { | ||||
|   EventScannerData esd; | ||||
|   XEvent useless; | ||||
|  | ||||
|   /* This code is copied from Owen's GDK code. */ | ||||
|  | ||||
|   if (window->display->grab_motion_notify_time != 0) | ||||
|     { | ||||
|       /* == is really the right test, but I'm all for paranoia */ | ||||
|       if (window->display->grab_motion_notify_time <= | ||||
|           xev->time) | ||||
|         { | ||||
|           meta_topic (META_DEBUG_RESIZING, | ||||
|                       "Arrived at event with time %u (waiting for %u), using it\n", | ||||
|                       (unsigned int)xev->time, | ||||
|                       window->display->grab_motion_notify_time); | ||||
|           window->display->grab_motion_notify_time = 0; | ||||
|           return TRUE; | ||||
|         } | ||||
|       else | ||||
|         return FALSE; /* haven't reached the saved timestamp yet */ | ||||
|     } | ||||
|  | ||||
|   esd.window = xev->event; | ||||
|   esd.count = 0; | ||||
|   esd.last_time = 0; | ||||
|  | ||||
|   /* "useless" isn't filled in because the predicate never returns True */ | ||||
|   XCheckIfEvent (window->display->xdisplay, | ||||
|                  &useless, | ||||
|                  find_last_time_predicate, | ||||
|                  (XPointer) &esd); | ||||
|  | ||||
|   if (esd.count > 0) | ||||
|     meta_topic (META_DEBUG_RESIZING, | ||||
|                 "Will skip %d motion events and use the event with time %u\n", | ||||
|                 esd.count, (unsigned int) esd.last_time); | ||||
|  | ||||
|   if (esd.last_time == 0) | ||||
|     return TRUE; | ||||
|   else | ||||
|     { | ||||
|       /* Save this timestamp, and ignore all motion notify | ||||
|        * until we get to the one with this stamp. | ||||
|        */ | ||||
|       window->display->grab_motion_notify_time = esd.last_time; | ||||
|       return FALSE; | ||||
|     } | ||||
|   /* XXX: Previously this code would walk through the X event queue | ||||
|      and filter out motion events that are followed by a later motion | ||||
|      event. There currently isn't any API to do the equivalent | ||||
|      procedure with the Clutter event queue so this function does | ||||
|      nothing. Clutter does its own motion event squashing so it may be | ||||
|      the case that this function isn't necessary. If it turns out that | ||||
|      we do need additional motion event squashing we could add some | ||||
|      extra API to the Clutter event queue and implement this function | ||||
|      properly. */ | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -10064,17 +9991,23 @@ meta_window_update_sync_request_counter (MetaWindow *window, | ||||
| #endif /* HAVE_XSYNC */ | ||||
|  | ||||
| void | ||||
| meta_window_handle_mouse_grab_op_event (MetaWindow *window, | ||||
|                                         XIDeviceEvent *xev) | ||||
| meta_window_handle_mouse_grab_op_event (MetaWindow         *window, | ||||
|                                         const ClutterEvent *event) | ||||
| { | ||||
|   switch (xev->evtype) | ||||
|   gboolean is_window_root = (event->any.stage != NULL && | ||||
|                              window && | ||||
|                              window->screen && | ||||
|                              CLUTTER_ACTOR (event->any.stage) == | ||||
|                              meta_get_stage_for_screen (window->screen)); | ||||
|  | ||||
|   switch (event->type) | ||||
|     { | ||||
|     case XI_ButtonRelease: | ||||
|       if (xev->detail == 1) | ||||
|     case CLUTTER_BUTTON_RELEASE: | ||||
|       if (event->button.button == 1) | ||||
|         { | ||||
|           meta_display_check_threshold_reached (window->display, | ||||
|                                                 xev->root_x, | ||||
|                                                 xev->root_y); | ||||
|                                                 event->button.x, | ||||
|                                                 event->button.y); | ||||
|           /* If the user was snap moving then ignore the button | ||||
|            * release because they may have let go of shift before | ||||
|            * releasing the mouse button and they almost certainly do | ||||
| @@ -10087,19 +10020,19 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, | ||||
|                 { | ||||
|                   if (window->tile_mode != META_TILE_NONE) | ||||
|                     meta_window_tile (window); | ||||
|                   else if (xev->root == window->screen->xroot) | ||||
|                   else if (is_window_root) | ||||
|                     update_move (window, | ||||
|                                  xev->mods.effective & ShiftMask, | ||||
|                                  xev->root_x, | ||||
|                                  xev->root_y); | ||||
|                                  event->button.modifier_state & CLUTTER_SHIFT_MASK, | ||||
|                                  event->button.x, | ||||
|                                  event->button.y); | ||||
|                 } | ||||
|               else if (meta_grab_op_is_resizing (window->display->grab_op)) | ||||
|                 { | ||||
|                   if (xev->root == window->screen->xroot) | ||||
|                   if (is_window_root) | ||||
|                     update_resize (window, | ||||
|                                    xev->mods.effective & ShiftMask, | ||||
|                                    xev->root_x, | ||||
|                                    xev->root_y, | ||||
|                                    event->button.modifier_state & CLUTTER_SHIFT_MASK, | ||||
|                                    event->button.x, | ||||
|                                    event->button.y, | ||||
|                                    TRUE); | ||||
|  | ||||
|                   /* If a tiled window has been dragged free with a | ||||
| @@ -10111,37 +10044,36 @@ meta_window_handle_mouse_grab_op_event (MetaWindow *window, | ||||
|                    */ | ||||
|                   update_tile_mode (window); | ||||
|                 } | ||||
|  | ||||
|               meta_display_end_grab_op (window->display, event->any.time); | ||||
|             } | ||||
|           meta_display_end_grab_op (window->display, xev->time); | ||||
|         } | ||||
|       break; | ||||
|  | ||||
|     case XI_Motion: | ||||
|     case CLUTTER_MOTION: | ||||
|       meta_display_check_threshold_reached (window->display, | ||||
|                                             xev->root_x, | ||||
|                                             xev->root_y); | ||||
|                                             event->motion.x, | ||||
|                                             event->motion.y); | ||||
|       if (meta_grab_op_is_moving (window->display->grab_op)) | ||||
|         { | ||||
|           if (xev->root == window->screen->xroot) | ||||
|           if (is_window_root) | ||||
|             { | ||||
|               if (check_use_this_motion_notify (window, | ||||
|                                                 xev)) | ||||
|               if (check_use_this_motion_notify (window, event)) | ||||
|                 update_move (window, | ||||
|                              xev->mods.effective & ShiftMask, | ||||
|                              xev->root_x, | ||||
|                              xev->root_y); | ||||
|                              event->button.modifier_state & CLUTTER_SHIFT_MASK, | ||||
|                              event->motion.x, | ||||
|                              event->motion.y); | ||||
|             } | ||||
|         } | ||||
|       else if (meta_grab_op_is_resizing (window->display->grab_op)) | ||||
|         { | ||||
|           if (xev->root == window->screen->xroot) | ||||
|           if (is_window_root) | ||||
|             { | ||||
|               if (check_use_this_motion_notify (window, | ||||
|                                                 xev)) | ||||
|               if (check_use_this_motion_notify (window, event)) | ||||
|                 update_resize (window, | ||||
|                                xev->mods.effective & ShiftMask, | ||||
|                                xev->root_x, | ||||
|                                xev->root_y, | ||||
|                                event->button.modifier_state & CLUTTER_SHIFT_MASK, | ||||
|                                event->motion.x, | ||||
|                                event->motion.y, | ||||
|                                FALSE); | ||||
|             } | ||||
|         } | ||||
| @@ -11737,3 +11669,185 @@ meta_window_set_transient_for (MetaWindow *window, | ||||
|   if (meta_window_appears_focused (window) && window->transient_for != None) | ||||
|     meta_window_propagate_focus_appearance (window, TRUE); | ||||
| } | ||||
|  | ||||
| static void | ||||
| reset_ignored_crossing_serials (MetaDisplay *display) | ||||
| { | ||||
|   int i; | ||||
|  | ||||
|   i = 0; | ||||
|   while (i < N_IGNORED_CROSSING_SERIALS) | ||||
|     { | ||||
|       display->ignored_crossing_serials[i] = 0; | ||||
|       ++i; | ||||
|     } | ||||
|  | ||||
|   display->ungrab_should_not_cause_focus_window = None; | ||||
| } | ||||
|  | ||||
| typedef struct | ||||
| { | ||||
|   MetaWindow *window; | ||||
|   int pointer_x; | ||||
|   int pointer_y; | ||||
| } MetaFocusData; | ||||
|  | ||||
| static void | ||||
| mouse_mode_focus (MetaWindow  *window, | ||||
|                   guint32      timestamp) | ||||
| { | ||||
|   MetaDisplay *display = window->display; | ||||
|  | ||||
|   if (window->type != META_WINDOW_DESKTOP) | ||||
|     { | ||||
|       meta_topic (META_DEBUG_FOCUS, | ||||
|                   "Focusing %s at time %u.\n", window->desc, timestamp); | ||||
|  | ||||
|       meta_window_focus (window, timestamp); | ||||
|  | ||||
|       if (meta_prefs_get_auto_raise ()) | ||||
|         meta_display_queue_autoraise_callback (display, window); | ||||
|       else | ||||
|         meta_topic (META_DEBUG_FOCUS, "Auto raise is disabled\n"); | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       /* In mouse focus mode, we defocus when the mouse *enters* | ||||
|        * the DESKTOP window, instead of defocusing on LeaveNotify. | ||||
|        * This is because having the mouse enter override-redirect | ||||
|        * child windows unfortunately causes LeaveNotify events that | ||||
|        * we can't distinguish from the mouse actually leaving the | ||||
|        * toplevel window as we expect.  But, since we filter out | ||||
|        * EnterNotify events on override-redirect windows, this | ||||
|        * alternative mechanism works great. | ||||
|        */ | ||||
|       if (meta_prefs_get_focus_mode() == G_DESKTOP_FOCUS_MODE_MOUSE && | ||||
|           display->focus_window != NULL) | ||||
|         { | ||||
|           meta_topic (META_DEBUG_FOCUS, | ||||
|                       "Unsetting focus from %s due to mouse entering " | ||||
|                       "the DESKTOP window\n", | ||||
|                       display->focus_window->desc); | ||||
|           meta_display_focus_the_no_focus_window (display, | ||||
|                                                   window->screen, | ||||
|                                                   timestamp); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| window_focus_on_pointer_rest_callback (gpointer data) | ||||
| { | ||||
|   MetaFocusData *focus_data = data; | ||||
|   MetaWindow *window = focus_data->window; | ||||
|   MetaDisplay *display = window->display; | ||||
|   MetaScreen *screen = window->screen; | ||||
|   Window root, child; | ||||
|   double root_x, root_y, x, y; | ||||
|   guint32 timestamp; | ||||
|   XIButtonState buttons; | ||||
|   XIModifierState mods; | ||||
|   XIGroupState group; | ||||
|  | ||||
|   if (meta_prefs_get_focus_mode () == G_DESKTOP_FOCUS_MODE_CLICK) | ||||
|     goto out; | ||||
|  | ||||
|   meta_error_trap_push (display); | ||||
|   XIQueryPointer (display->xdisplay, | ||||
|                   META_VIRTUAL_CORE_POINTER_ID, | ||||
|                   screen->xroot, | ||||
|                   &root, &child, | ||||
|                   &root_x, &root_y, &x, &y, | ||||
|                   &buttons, &mods, &group); | ||||
|   meta_error_trap_pop (display); | ||||
|   free (buttons.mask); | ||||
|  | ||||
|   if (root_x != focus_data->pointer_x || | ||||
|       root_y != focus_data->pointer_y) | ||||
|     { | ||||
|       focus_data->pointer_x = root_x; | ||||
|       focus_data->pointer_y = root_y; | ||||
|       return TRUE; | ||||
|     } | ||||
|  | ||||
|   /* Explicitly check for the overlay window, as get_focus_window_at_point() | ||||
|    * may return windows that extend underneath the chrome (like | ||||
|    * override-redirect or DESKTOP windows) | ||||
|    */ | ||||
|   if (child == meta_get_overlay_window (screen)) | ||||
|     goto out; | ||||
|  | ||||
|   window = | ||||
|     meta_stack_get_default_focus_window_at_point (screen->stack, | ||||
|                                                   screen->active_workspace, | ||||
|                                                   None, root_x, root_y); | ||||
|  | ||||
|   if (window == NULL) | ||||
|     goto out; | ||||
|  | ||||
|   timestamp = meta_display_get_current_time_roundtrip (display); | ||||
|   mouse_mode_focus (window, timestamp); | ||||
|  | ||||
|  out: | ||||
|   display->focus_timeout_id = 0; | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| /* The interval, in milliseconds, we use in focus-follows-mouse | ||||
|  * mode to check whether the pointer has stopped moving after a | ||||
|  * crossing event. | ||||
|  */ | ||||
| #define FOCUS_TIMEOUT_DELAY 25 | ||||
|  | ||||
| static void | ||||
| queue_focus_callback (MetaDisplay *display, | ||||
|                       MetaWindow  *window, | ||||
|                       int          pointer_x, | ||||
|                       int          pointer_y) | ||||
| { | ||||
|   MetaFocusData *focus_data; | ||||
|  | ||||
|   focus_data = g_new (MetaFocusData, 1); | ||||
|   focus_data->window = window; | ||||
|   focus_data->pointer_x = pointer_x; | ||||
|   focus_data->pointer_y = pointer_y; | ||||
|  | ||||
|   if (display->focus_timeout_id != 0) | ||||
|     g_source_remove (display->focus_timeout_id); | ||||
|  | ||||
|   display->focus_timeout_id = | ||||
|     g_timeout_add_full (G_PRIORITY_DEFAULT, | ||||
|                         FOCUS_TIMEOUT_DELAY, | ||||
|                         window_focus_on_pointer_rest_callback, | ||||
|                         focus_data, | ||||
|                         g_free); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_window_handle_enter (MetaWindow  *window, | ||||
|                           guint32      timestamp, | ||||
|                           guint        root_x, | ||||
|                           guint        root_y) | ||||
| { | ||||
|   MetaDisplay *display = window->display; | ||||
|  | ||||
|   switch (meta_prefs_get_focus_mode ()) | ||||
|     { | ||||
|     case G_DESKTOP_FOCUS_MODE_SLOPPY: | ||||
|     case G_DESKTOP_FOCUS_MODE_MOUSE: | ||||
|       display->mouse_mode = TRUE; | ||||
|       if (window->type != META_WINDOW_DOCK) | ||||
|         { | ||||
|           if (meta_prefs_get_focus_change_on_pointer_rest()) | ||||
|             queue_focus_callback (display, window, root_x, root_y); | ||||
|           else | ||||
|             mouse_mode_focus (window, timestamp); | ||||
|  | ||||
|           /* stop ignoring stuff */ | ||||
|           reset_ignored_crossing_serials (display); | ||||
|         } | ||||
|       break; | ||||
|     case G_DESKTOP_FOCUS_MODE_CLICK: | ||||
|       break; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -536,6 +536,81 @@ meta_prop_get_utf8_list (MetaDisplay   *display, | ||||
|   return utf8_list_from_results (&results, str_p, n_str_p); | ||||
| } | ||||
|  | ||||
| /* this one freakishly returns g_malloc memory */ | ||||
| static gboolean | ||||
| latin1_list_from_results (GetPropertyResults *results, | ||||
|                         char             ***str_p, | ||||
|                         int                *n_str_p) | ||||
| { | ||||
|   int i; | ||||
|   int n_strings; | ||||
|   char **retval; | ||||
|   const char *p; | ||||
|    | ||||
|   *str_p = NULL; | ||||
|   *n_str_p = 0; | ||||
|  | ||||
|   if (!validate_or_free_results (results, 8, XA_STRING, FALSE)) | ||||
|     return FALSE; | ||||
|    | ||||
|   /* I'm not sure this is right, but I'm guessing the | ||||
|    * property is nul-separated | ||||
|    */ | ||||
|   i = 0; | ||||
|   n_strings = 0; | ||||
|   while (i < (int) results->n_items) | ||||
|     { | ||||
|       if (results->prop[i] == '\0') | ||||
|         ++n_strings; | ||||
|       ++i; | ||||
|     } | ||||
|  | ||||
|   if (results->prop[results->n_items - 1] != '\0') | ||||
|     ++n_strings; | ||||
|   | ||||
|   /* we're guaranteed that results->prop has a nul on the end | ||||
|    * by XGetWindowProperty | ||||
|    */ | ||||
|    | ||||
|   retval = g_new0 (char*, n_strings + 1); | ||||
|  | ||||
|   p = (char *)results->prop; | ||||
|   i = 0; | ||||
|   while (i < n_strings) | ||||
|     { | ||||
|       retval[i] = g_strdup (p); | ||||
|        | ||||
|       p = p + strlen (p) + 1; | ||||
|       ++i; | ||||
|     } | ||||
|    | ||||
|   *str_p = retval; | ||||
|   *n_str_p = i; | ||||
|  | ||||
|   meta_XFree (results->prop); | ||||
|   results->prop = NULL; | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
|  | ||||
| gboolean | ||||
| meta_prop_get_latin1_list (MetaDisplay   *display, | ||||
|                            Window         xwindow, | ||||
|                            Atom           xatom, | ||||
|                            char        ***str_p, | ||||
|                            int           *n_str_p) | ||||
| { | ||||
|   GetPropertyResults results; | ||||
|  | ||||
|   *str_p = NULL; | ||||
|  | ||||
|   if (!get_property (display, xwindow, xatom, | ||||
|                      XA_STRING, &results)) | ||||
|     return FALSE; | ||||
|  | ||||
|   return latin1_list_from_results (&results, str_p, n_str_p); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_prop_set_utf8_string_hint (MetaDisplay *display, | ||||
|                                 Window xwindow, | ||||
|   | ||||
| @@ -102,6 +102,11 @@ gboolean meta_prop_get_utf8_list     (MetaDisplay   *display, | ||||
|                                       Atom           xatom, | ||||
|                                       char        ***str_p, | ||||
|                                       int           *n_str_p); | ||||
| gboolean meta_prop_get_latin1_list   (MetaDisplay   *display, | ||||
|                                       Window         xwindow, | ||||
|                                       Atom           xatom, | ||||
|                                       char        ***str_p, | ||||
|                                       int           *n_str_p); | ||||
| void     meta_prop_set_utf8_string_hint | ||||
|                                      (MetaDisplay *display, | ||||
|                                       Window xwindow, | ||||
|   | ||||
| @@ -81,6 +81,7 @@ item(TIMESTAMP) | ||||
| item(VERSION) | ||||
| item(ATOM_PAIR) | ||||
| item(BACKLIGHT) | ||||
| item(_XKB_RULES_NAMES) | ||||
|  | ||||
| /* Oddities: These are used, and we need atoms for them, | ||||
|  * but when we need all _NET_WM hints (i.e. when we're making | ||||
|   | ||||
| @@ -31,6 +31,7 @@ | ||||
| #include <X11/Xlib.h> | ||||
| #include <X11/extensions/XInput.h> | ||||
| #include <X11/extensions/XInput2.h> | ||||
| #include <clutter/clutter.h> | ||||
| #include <glib.h> | ||||
| #include <gtk/gtk.h> | ||||
|  | ||||
|   | ||||
| @@ -391,17 +391,17 @@ struct _MetaKeyCombo | ||||
|  * @display: a #MetaDisplay | ||||
|  * @screen: a #MetaScreen | ||||
|  * @window: a #MetaWindow | ||||
|  * @event: (type gpointer): a #XIDeviceEvent | ||||
|  * @event: a #ClutterKeyEvent | ||||
|  * @binding: a #MetaKeyBinding | ||||
|  * @user_data: data passed to the function | ||||
|  * | ||||
|  */ | ||||
| typedef void (* MetaKeyHandlerFunc) (MetaDisplay    *display, | ||||
|                                      MetaScreen     *screen, | ||||
|                                      MetaWindow     *window, | ||||
|                                      XIDeviceEvent  *event, | ||||
|                                      MetaKeyBinding *binding, | ||||
|                                      gpointer        user_data); | ||||
| typedef void (* MetaKeyHandlerFunc) (MetaDisplay     *display, | ||||
|                                      MetaScreen      *screen, | ||||
|                                      MetaWindow      *window, | ||||
|                                      ClutterKeyEvent *event, | ||||
|                                      MetaKeyBinding  *binding, | ||||
|                                      gpointer         user_data); | ||||
|  | ||||
| typedef struct _MetaKeyHandler MetaKeyHandler; | ||||
|  | ||||
|   | ||||
| @@ -106,11 +106,49 @@ create_anonymous_file (off_t size, | ||||
|   return -1; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info) | ||||
| static void | ||||
| inform_clients_of_new_keymap (MetaWaylandKeyboard *keyboard, | ||||
| 			      int                  flags) | ||||
| { | ||||
|   MetaWaylandCompositor *compositor; | ||||
|   struct wl_client *xclient; | ||||
|   struct wl_resource *keyboard_resource; | ||||
|  | ||||
|   compositor = meta_wayland_compositor_get_default (); | ||||
|   xclient = compositor->xwayland_client; | ||||
|  | ||||
|   wl_resource_for_each (keyboard_resource, &keyboard->resource_list) | ||||
|     { | ||||
|       if ((flags & META_WAYLAND_KEYBOARD_SKIP_XCLIENTS) && | ||||
| 	  wl_resource_get_client (keyboard_resource) == xclient) | ||||
| 	continue; | ||||
|  | ||||
|       wl_keyboard_send_keymap (keyboard_resource, | ||||
| 			       WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1, | ||||
| 			       keyboard->xkb_info.keymap_fd, | ||||
| 			       keyboard->xkb_info.keymap_size); | ||||
|     } | ||||
| } | ||||
|  | ||||
| static void | ||||
| meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard, | ||||
| 				   struct xkb_keymap   *keymap, | ||||
| 				   int                  flags) | ||||
| { | ||||
|   MetaWaylandXkbInfo  *xkb_info = &keyboard->xkb_info; | ||||
|   GError *error = NULL; | ||||
|   char *keymap_str; | ||||
|   size_t previous_size; | ||||
|  | ||||
|   if (keymap == NULL) | ||||
|     { | ||||
|       g_warning ("Attempting to set null keymap (compilation probably failed)"); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|   if (xkb_info->keymap) | ||||
|     xkb_keymap_unref (xkb_info->keymap); | ||||
|   xkb_info->keymap = keymap; | ||||
|  | ||||
|   xkb_info->shift_mod = | ||||
|     xkb_map_mod_get_index (xkb_info->keymap, XKB_MOD_NAME_SHIFT); | ||||
| @@ -129,21 +167,28 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info) | ||||
|   keymap_str = xkb_map_get_as_string (xkb_info->keymap); | ||||
|   if (keymap_str == NULL) | ||||
|     { | ||||
|       g_warning ("failed to get string version of keymap\n"); | ||||
|       return FALSE; | ||||
|       g_warning ("failed to get string version of keymap"); | ||||
|       return; | ||||
|     } | ||||
|   previous_size = xkb_info->keymap_size; | ||||
|   xkb_info->keymap_size = strlen (keymap_str) + 1; | ||||
|  | ||||
|   if (xkb_info->keymap_fd >= 0) | ||||
|     close (xkb_info->keymap_fd); | ||||
|  | ||||
|   xkb_info->keymap_fd = create_anonymous_file (xkb_info->keymap_size, &error); | ||||
|   if (xkb_info->keymap_fd < 0) | ||||
|     { | ||||
|       g_warning ("creating a keymap file for %lu bytes failed: %s\n", | ||||
|       g_warning ("creating a keymap file for %lu bytes failed: %s", | ||||
|                  (unsigned long) xkb_info->keymap_size, | ||||
|                  error->message); | ||||
|       g_clear_error (&error); | ||||
|       goto err_keymap_str; | ||||
|     } | ||||
|  | ||||
|   if (xkb_info->keymap_area) | ||||
|     munmap (xkb_info->keymap_area, previous_size); | ||||
|  | ||||
|   xkb_info->keymap_area = mmap (NULL, xkb_info->keymap_size, | ||||
|                                 PROT_READ | PROT_WRITE, | ||||
|                                 MAP_SHARED, xkb_info->keymap_fd, 0); | ||||
| @@ -156,41 +201,24 @@ meta_wayland_xkb_info_new_keymap (MetaWaylandXkbInfo *xkb_info) | ||||
|   strcpy (xkb_info->keymap_area, keymap_str); | ||||
|   free (keymap_str); | ||||
|  | ||||
|   return TRUE; | ||||
|   if (keyboard->is_evdev) | ||||
|     { | ||||
|       ClutterDeviceManager *manager; | ||||
|  | ||||
|       manager = clutter_device_manager_get_default (); | ||||
|       clutter_evdev_set_keyboard_map (manager, xkb_info->keymap); | ||||
|     } | ||||
|  | ||||
|   inform_clients_of_new_keymap (keyboard, flags); | ||||
|  | ||||
|   return; | ||||
|  | ||||
| err_dev_zero: | ||||
|   close (xkb_info->keymap_fd); | ||||
|   xkb_info->keymap_fd = -1; | ||||
| err_keymap_str: | ||||
|   free (keymap_str); | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| meta_wayland_keyboard_build_global_keymap (struct xkb_context *xkb_context, | ||||
|                                            struct xkb_rule_names *xkb_names, | ||||
|                                            MetaWaylandXkbInfo *xkb_info) | ||||
| { | ||||
|   xkb_info->keymap = xkb_map_new_from_names (xkb_context, | ||||
|                                              xkb_names, | ||||
|                                              0 /* flags */); | ||||
|   if (xkb_info->keymap == NULL) | ||||
|     { | ||||
|       g_warning ("failed to compile global XKB keymap\n" | ||||
|                  "  tried rules %s, model %s, layout %s, variant %s, " | ||||
|                  "options %s\n", | ||||
|                  xkb_names->rules, | ||||
|                  xkb_names->model, | ||||
|                  xkb_names->layout, | ||||
|                  xkb_names->variant, | ||||
|                  xkb_names->options); | ||||
|       return FALSE; | ||||
|     } | ||||
|  | ||||
|   if (!meta_wayland_xkb_info_new_keymap (xkb_info)) | ||||
|     return FALSE; | ||||
|  | ||||
|   return TRUE; | ||||
|   return; | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -306,9 +334,8 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, | ||||
|                             struct wl_display   *display, | ||||
| 			    gboolean             is_evdev) | ||||
| { | ||||
|   ClutterDeviceManager *manager; | ||||
|  | ||||
|   memset (keyboard, 0, sizeof *keyboard); | ||||
|   keyboard->xkb_info.keymap_fd = -1; | ||||
|  | ||||
|   wl_list_init (&keyboard->resource_list); | ||||
|   wl_array_init (&keyboard->keys); | ||||
| @@ -320,18 +347,15 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, | ||||
|   keyboard->display = display; | ||||
|  | ||||
|   keyboard->xkb_context = xkb_context_new (0 /* flags */); | ||||
|  | ||||
|   meta_wayland_keyboard_build_global_keymap (keyboard->xkb_context, | ||||
| 					     &keyboard->xkb_names, | ||||
| 					     &keyboard->xkb_info); | ||||
|  | ||||
|   keyboard->is_evdev = is_evdev; | ||||
|   if (is_evdev) | ||||
|     { | ||||
|       manager = clutter_device_manager_get_default (); | ||||
|  | ||||
|       clutter_evdev_set_keyboard_map (manager, keyboard->xkb_info.keymap); | ||||
|     } | ||||
|   /* Compute a default until gnome-settings-daemon starts and sets | ||||
|      the appropriate values | ||||
|   */ | ||||
|   meta_wayland_keyboard_set_keymap_names (keyboard, | ||||
| 					  "evdev", | ||||
| 					  "pc105", | ||||
| 					  "us", "", "", 0); | ||||
|  | ||||
|   return TRUE; | ||||
| } | ||||
| @@ -559,12 +583,6 @@ meta_wayland_keyboard_end_grab (MetaWaylandKeyboard *keyboard) | ||||
| void | ||||
| meta_wayland_keyboard_release (MetaWaylandKeyboard *keyboard) | ||||
| { | ||||
|   g_free ((char *) keyboard->xkb_names.rules); | ||||
|   g_free ((char *) keyboard->xkb_names.model); | ||||
|   g_free ((char *) keyboard->xkb_names.layout); | ||||
|   g_free ((char *) keyboard->xkb_names.variant); | ||||
|   g_free ((char *) keyboard->xkb_names.options); | ||||
|  | ||||
|   meta_wayland_xkb_info_destroy (&keyboard->xkb_info); | ||||
|   xkb_context_unref (keyboard->xkb_context); | ||||
|  | ||||
| @@ -652,3 +670,28 @@ meta_wayland_keyboard_end_modal (MetaWaylandKeyboard *keyboard, | ||||
|  | ||||
|   meta_verbose ("Released modal keyboard grab, timestamp %d\n", timestamp); | ||||
| } | ||||
|  | ||||
| void | ||||
| meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard, | ||||
| 					const char          *rules, | ||||
| 					const char          *model, | ||||
| 					const char          *layout, | ||||
| 					const char          *variant, | ||||
| 					const char          *options, | ||||
| 					int                  flags) | ||||
| { | ||||
|   struct xkb_rule_names xkb_names; | ||||
|  | ||||
|   xkb_names.rules = rules; | ||||
|   xkb_names.model = model; | ||||
|   xkb_names.layout = layout; | ||||
|   xkb_names.variant = variant; | ||||
|   xkb_names.options = options; | ||||
|  | ||||
|   meta_wayland_keyboard_take_keymap (keyboard, | ||||
| 				     xkb_keymap_new_from_names (keyboard->xkb_context, | ||||
| 								&xkb_names, | ||||
| 								0 /* flags */), | ||||
| 				     flags); | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -112,7 +112,6 @@ struct _MetaWaylandKeyboard | ||||
|   struct xkb_context *xkb_context; | ||||
|   gboolean is_evdev; | ||||
|   MetaWaylandXkbInfo xkb_info; | ||||
|   struct xkb_rule_names xkb_names; | ||||
|  | ||||
|   MetaWaylandKeyboardGrab input_method_grab; | ||||
|   struct wl_resource *input_method_resource; | ||||
| @@ -123,6 +122,18 @@ meta_wayland_keyboard_init (MetaWaylandKeyboard *keyboard, | ||||
|                             struct wl_display   *display, | ||||
| 			    gboolean             is_evdev); | ||||
|  | ||||
| typedef enum { | ||||
|   META_WAYLAND_KEYBOARD_SKIP_XCLIENTS = 1, | ||||
| } MetaWaylandKeyboardSetKeymapFlags; | ||||
|  | ||||
| void | ||||
| meta_wayland_keyboard_set_keymap_names (MetaWaylandKeyboard *keyboard, | ||||
| 					const char          *rules, | ||||
| 					const char          *model, | ||||
| 					const char          *layout, | ||||
| 					const char          *variant, | ||||
| 					const char          *options, | ||||
| 					int                  flags); | ||||
| gboolean | ||||
| meta_wayland_keyboard_handle_event (MetaWaylandKeyboard *keyboard, | ||||
|                                     const ClutterKeyEvent *event); | ||||
|   | ||||
| @@ -352,6 +352,11 @@ meta_wayland_pointer_set_focus (MetaWaylandPointer *pointer, | ||||
|         } | ||||
|  | ||||
|       meta_wayland_pointer_get_relative_coordinates (pointer, surface, &sx, &sy); | ||||
|       meta_window_handle_enter (surface->window, | ||||
|                                 /* XXX -- can we reliably get a timestamp for setting focus? */ | ||||
|                                 clutter_get_current_event_time (), | ||||
|                                 wl_fixed_to_int (pointer->x), | ||||
|                                 wl_fixed_to_int (pointer->y)); | ||||
|       wl_pointer_send_enter (resource, serial, surface->resource, sx, sy); | ||||
|       wl_resource_add_destroy_listener (resource, &pointer->focus_listener); | ||||
|       pointer->focus_serial = serial; | ||||
|   | ||||
| @@ -62,7 +62,6 @@ struct _MetaWaylandPointer | ||||
|  | ||||
|   wl_fixed_t x, y; /* TODO: remove, use ClutterInputDevice instead */ | ||||
|   MetaWaylandSurface *current; | ||||
|   wl_fixed_t current_x, current_y; | ||||
|  | ||||
|   guint32 button_count; | ||||
| }; | ||||
|   | ||||
| @@ -83,14 +83,6 @@ struct _MetaWaylandCompositor | ||||
|   int drm_fd; | ||||
|  | ||||
|   MetaWaylandSeat *seat; | ||||
|  | ||||
|   /* This surface is only used to keep drag of the implicit grab when | ||||
|      synthesizing XEvents for Mutter */ | ||||
|   MetaWaylandSurface *implicit_grab_surface; | ||||
|   /* Button that was pressed to initiate an implicit grab. The | ||||
|      implicit grab will only be released when this button is | ||||
|      released */ | ||||
|   guint32 implicit_grab_button; | ||||
| }; | ||||
|  | ||||
| void                    meta_wayland_init                       (void); | ||||
| @@ -104,6 +96,8 @@ void                    meta_wayland_compositor_repick          (MetaWaylandComp | ||||
|  | ||||
| void                    meta_wayland_compositor_set_input_focus (MetaWaylandCompositor *compositor, | ||||
|                                                                  MetaWindow            *window); | ||||
| gboolean                meta_wayland_compositor_handle_event    (MetaWaylandCompositor *compositor, | ||||
|                                                                  const ClutterEvent    *event); | ||||
|  | ||||
| MetaLauncher           *meta_wayland_compositor_get_launcher    (MetaWaylandCompositor *compositor); | ||||
| gboolean                meta_wayland_compositor_is_native       (MetaWaylandCompositor *compositor); | ||||
|   | ||||
| @@ -280,31 +280,9 @@ handle_button_event (MetaWaylandSeat    *seat, | ||||
|                      const ClutterEvent *event) | ||||
| { | ||||
|   MetaWaylandPointer *pointer = &seat->pointer; | ||||
|   gboolean state = event->type == CLUTTER_BUTTON_PRESS; | ||||
|   uint32_t button; | ||||
|   MetaWaylandSurface *surface; | ||||
|  | ||||
|   notify_motion (seat, event); | ||||
|  | ||||
|   if (state && pointer->button_count == 1) | ||||
|     { | ||||
|       button = clutter_event_get_button (event); | ||||
|       pointer->grab_button = button; | ||||
|       pointer->grab_time = clutter_event_get_time (event); | ||||
|       pointer->grab_x = pointer->x; | ||||
|       pointer->grab_y = pointer->y; | ||||
|  | ||||
|       /* FIXME: synth a XI2 event and handle in display.c */ | ||||
|       surface = pointer->current; | ||||
|       if (button == CLUTTER_BUTTON_PRIMARY && | ||||
| 	  surface && | ||||
| 	  surface->window && | ||||
| 	  surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) | ||||
| 	{ | ||||
| 	  meta_window_raise (surface->window); | ||||
| 	} | ||||
|     } | ||||
|  | ||||
|   pointer->grab->interface->button (pointer->grab, event); | ||||
|  | ||||
|   if (pointer->button_count == 1) | ||||
| @@ -381,6 +359,19 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat, | ||||
| { | ||||
|   seat->pointer.button_count = count_buttons (event); | ||||
|  | ||||
|   if (seat->cursor_tracker) | ||||
|     { | ||||
|       meta_cursor_tracker_update_position (seat->cursor_tracker, | ||||
| 					   wl_fixed_to_int (seat->pointer.x), | ||||
| 					   wl_fixed_to_int (seat->pointer.y)); | ||||
|  | ||||
|       if (seat->pointer.current == NULL) | ||||
| 	meta_cursor_tracker_revert_root (seat->cursor_tracker); | ||||
|  | ||||
|       meta_cursor_tracker_queue_redraw (seat->cursor_tracker, | ||||
|                                         CLUTTER_ACTOR (event->any.stage)); | ||||
|     } | ||||
|  | ||||
|   switch (event->type) | ||||
|     { | ||||
|     case CLUTTER_MOTION: | ||||
| @@ -408,20 +399,6 @@ meta_wayland_seat_handle_event (MetaWaylandSeat *seat, | ||||
|   return FALSE; | ||||
| } | ||||
|  | ||||
| static void | ||||
| update_pointer_position_for_actor (MetaWaylandPointer *pointer, | ||||
|                                    ClutterActor *actor) | ||||
| { | ||||
|   float ax, ay; | ||||
|  | ||||
|   clutter_actor_transform_stage_point (actor, | ||||
|                                        wl_fixed_to_double (pointer->x), | ||||
|                                        wl_fixed_to_double (pointer->y), | ||||
|                                        &ax, &ay); | ||||
|   pointer->current_x = wl_fixed_from_double (ax); | ||||
|   pointer->current_y = wl_fixed_from_double (ay); | ||||
| } | ||||
|  | ||||
| /* The actor argument can be NULL in which case a Clutter pick will be | ||||
|    performed to determine the right actor. An actor should only be | ||||
|    passed if the repick is being performed due to an event in which | ||||
| @@ -458,16 +435,12 @@ meta_wayland_seat_repick (MetaWaylandSeat    *seat, | ||||
|       MetaWindow *window = | ||||
|         meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor)); | ||||
|  | ||||
|       update_pointer_position_for_actor (pointer, actor); | ||||
|  | ||||
|       surface = window->surface; | ||||
|     } | ||||
|   else if (META_IS_SHAPED_TEXTURE (actor)) | ||||
|     { | ||||
|       MetaShapedTexture *shaped_texture = META_SHAPED_TEXTURE (actor); | ||||
|  | ||||
|       update_pointer_position_for_actor (pointer, actor); | ||||
|  | ||||
|       surface = meta_shaped_texture_get_wayland_surface (shaped_texture); | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -409,9 +409,6 @@ meta_wayland_surface_free (MetaWaylandSurface *surface) | ||||
|       g_assert (surface != compositor->seat->pointer.focus); | ||||
|     } | ||||
|  | ||||
|  if (compositor->implicit_grab_surface == surface) | ||||
|    compositor->implicit_grab_surface = compositor->seat->pointer.current; | ||||
|  | ||||
|   if (surface->resource) | ||||
|     wl_resource_set_user_data (surface->resource, NULL); | ||||
|   g_slice_free (MetaWaylandSurface, surface); | ||||
|   | ||||
| @@ -533,119 +533,6 @@ stage_destroy_cb (void) | ||||
|   meta_quit (META_EXIT_SUCCESS); | ||||
| } | ||||
|  | ||||
| #define N_BUTTONS 5 | ||||
|  | ||||
| static void | ||||
| synthesize_motion_event (MetaWaylandCompositor *compositor, | ||||
|                          const ClutterEvent *event) | ||||
| { | ||||
|   /* We want to synthesize X events for mouse motion events so that we | ||||
|      don't have to rely on the X server's window position being | ||||
|      synched with the surface position. See the comment in | ||||
|      event_callback() in display.c */ | ||||
|   MetaWaylandSeat *seat = compositor->seat; | ||||
|   MetaWaylandPointer *pointer = &seat->pointer; | ||||
|   MetaWaylandSurface *surface; | ||||
|   XGenericEventCookie generic_event; | ||||
|   XIDeviceEvent device_event; | ||||
|   unsigned char button_mask[(N_BUTTONS + 7) / 8] = { 0 }; | ||||
|   MetaDisplay *display = meta_get_display (); | ||||
|   ClutterModifierType button_state; | ||||
|   int i; | ||||
|  | ||||
|   generic_event.type = GenericEvent; | ||||
|   generic_event.serial = 0; | ||||
|   generic_event.send_event = False; | ||||
|   generic_event.display = display->xdisplay; | ||||
|   generic_event.extension = display->xinput_opcode; | ||||
|   generic_event.evtype = XI_Motion; | ||||
|   /* Mutter assumes the data for the event is already retrieved by GDK | ||||
|    * so we don't need the cookie */ | ||||
|   generic_event.cookie = 0; | ||||
|   generic_event.data = &device_event; | ||||
|  | ||||
|   memcpy (&device_event, &generic_event, sizeof (XGenericEvent)); | ||||
|  | ||||
|   device_event.time = clutter_event_get_time (event); | ||||
|   device_event.deviceid = clutter_event_get_device_id (event); | ||||
|   device_event.sourceid = 0; /* not used, not sure what this should be */ | ||||
|   device_event.detail = 0; | ||||
|   device_event.root = DefaultRootWindow (display->xdisplay); | ||||
|   device_event.flags = 0 /* not used for motion events */; | ||||
|  | ||||
|   if (compositor->implicit_grab_surface) | ||||
|     surface = compositor->implicit_grab_surface; | ||||
|   else | ||||
|     surface = pointer->current; | ||||
|  | ||||
|   if (surface == pointer->current) | ||||
|     { | ||||
|       device_event.event_x = wl_fixed_to_int (pointer->current_x); | ||||
|       device_event.event_y = wl_fixed_to_int (pointer->current_y); | ||||
|     } | ||||
|   else if (surface && surface->window) | ||||
|     { | ||||
|       ClutterActor *window_actor = | ||||
|         CLUTTER_ACTOR (meta_window_get_compositor_private (surface->window)); | ||||
|  | ||||
|       if (window_actor) | ||||
|         { | ||||
|           float ax, ay; | ||||
|  | ||||
|           clutter_actor_transform_stage_point (window_actor, | ||||
|                                                wl_fixed_to_double (pointer->x), | ||||
|                                                wl_fixed_to_double (pointer->y), | ||||
|                                                &ax, &ay); | ||||
|  | ||||
|           device_event.event_x = ax; | ||||
|           device_event.event_y = ay; | ||||
|         } | ||||
|       else | ||||
|         { | ||||
|           device_event.event_x = wl_fixed_to_double (pointer->x); | ||||
|           device_event.event_y = wl_fixed_to_double (pointer->y); | ||||
|         } | ||||
|     } | ||||
|   else | ||||
|     { | ||||
|       device_event.event_x = wl_fixed_to_double (pointer->x); | ||||
|       device_event.event_y = wl_fixed_to_double (pointer->y); | ||||
|     } | ||||
|  | ||||
|   if (surface && surface->window != NULL) | ||||
|     device_event.event = surface->window->xwindow; | ||||
|   else | ||||
|     device_event.event = device_event.root; | ||||
|  | ||||
|   /* Mutter doesn't really know about the sub-windows. This assumes it | ||||
|      doesn't care either */ | ||||
|   device_event.child = device_event.event; | ||||
|   device_event.root_x = wl_fixed_to_double (pointer->x); | ||||
|   device_event.root_y = wl_fixed_to_double (pointer->y); | ||||
|  | ||||
|   clutter_event_get_state_full (event, | ||||
| 				&button_state, | ||||
| 				(ClutterModifierType*)&device_event.mods.base, | ||||
| 				(ClutterModifierType*)&device_event.mods.latched, | ||||
| 				(ClutterModifierType*)&device_event.mods.locked, | ||||
| 				(ClutterModifierType*)&device_event.mods.effective); | ||||
|   device_event.mods.effective &= ~button_state; | ||||
|   memset (&device_event.group, 0, sizeof (device_event.group)); | ||||
|   device_event.group.effective = (device_event.mods.effective >> 13) & 0x3; | ||||
|  | ||||
|   for (i = 0; i < N_BUTTONS; i++) | ||||
|     if ((button_state & (CLUTTER_BUTTON1_MASK << i))) | ||||
|       XISetMask (button_mask, i + 1); | ||||
|   device_event.buttons.mask_len = N_BUTTONS + 1; | ||||
|   device_event.buttons.mask = button_mask; | ||||
|  | ||||
|   device_event.valuators.mask_len = 0; | ||||
|   device_event.valuators.mask = NULL; | ||||
|   device_event.valuators.values = NULL; | ||||
|  | ||||
|   meta_display_handle_event (display, (XEvent *) &generic_event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| reset_idletimes (const ClutterEvent *event) | ||||
| { | ||||
| @@ -671,132 +558,13 @@ reset_idletimes (const ClutterEvent *event) | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| event_cb (ClutterActor *stage, | ||||
|           const ClutterEvent *event, | ||||
|           MetaWaylandCompositor *compositor) | ||||
| gboolean | ||||
| meta_wayland_compositor_handle_event (MetaWaylandCompositor *compositor, | ||||
|                                       const ClutterEvent    *event) | ||||
| { | ||||
|   MetaWaylandSeat *seat = compositor->seat; | ||||
|   MetaWaylandPointer *pointer = &seat->pointer; | ||||
|   MetaWaylandSurface *surface; | ||||
|   MetaDisplay *display; | ||||
|  | ||||
|   reset_idletimes (event); | ||||
|  | ||||
|   if (meta_wayland_seat_handle_event (compositor->seat, event)) | ||||
|     return TRUE; | ||||
|  | ||||
|   /* HACK: for now, the surfaces from Wayland clients aren't | ||||
|      integrated into Mutter's event handling and Mutter won't give them | ||||
|      focus on mouse clicks. As a hack to work around this we can just | ||||
|      give them input focus on mouse clicks so we can at least test the | ||||
|      keyboard support */ | ||||
|   if (event->type == CLUTTER_BUTTON_PRESS) | ||||
|     { | ||||
|       surface = pointer->current; | ||||
|  | ||||
|       if (surface && surface->window && | ||||
| 	  surface->window->client_type == META_WINDOW_CLIENT_TYPE_WAYLAND) | ||||
|         { | ||||
| 	  MetaDisplay *display = meta_get_display (); | ||||
| 	  guint32 timestamp = meta_display_get_current_time_roundtrip (display); | ||||
|  | ||||
| 	  meta_window_focus (surface->window, timestamp); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   if (seat->cursor_tracker) | ||||
|     { | ||||
|       meta_cursor_tracker_update_position (seat->cursor_tracker, | ||||
| 					   wl_fixed_to_int (pointer->x), | ||||
| 					   wl_fixed_to_int (pointer->y)); | ||||
|  | ||||
|       if (pointer->current == NULL) | ||||
| 	meta_cursor_tracker_revert_root (seat->cursor_tracker); | ||||
|  | ||||
|       meta_cursor_tracker_queue_redraw (seat->cursor_tracker, stage); | ||||
|     } | ||||
|  | ||||
|   display = meta_get_display (); | ||||
|   if (!display) | ||||
|     return FALSE; | ||||
|  | ||||
|   switch (event->type) | ||||
|     { | ||||
|     case CLUTTER_BUTTON_PRESS: | ||||
|       if (compositor->implicit_grab_surface == NULL) | ||||
|         { | ||||
|           compositor->implicit_grab_button = event->button.button; | ||||
|           compositor->implicit_grab_surface = pointer->current; | ||||
|         } | ||||
|       return FALSE; | ||||
|  | ||||
|     case CLUTTER_BUTTON_RELEASE: | ||||
|       if (event->type == CLUTTER_BUTTON_RELEASE && | ||||
|           compositor->implicit_grab_surface && | ||||
|           event->button.button == compositor->implicit_grab_button) | ||||
|         compositor->implicit_grab_surface = NULL; | ||||
|       return FALSE; | ||||
|  | ||||
|     case CLUTTER_MOTION: | ||||
|       synthesize_motion_event (compositor, event); | ||||
|       return FALSE; | ||||
|  | ||||
|     default: | ||||
|       return FALSE; | ||||
|     } | ||||
| } | ||||
|  | ||||
| static gboolean | ||||
| event_emission_hook_cb (GSignalInvocationHint *ihint, | ||||
|                         guint n_param_values, | ||||
|                         const GValue *param_values, | ||||
|                         gpointer data) | ||||
| { | ||||
|   MetaWaylandCompositor *compositor = data; | ||||
|   ClutterActor *actor; | ||||
|   ClutterEvent *event; | ||||
|  | ||||
|   g_return_val_if_fail (n_param_values == 2, FALSE); | ||||
|  | ||||
|   actor = g_value_get_object (param_values + 0); | ||||
|   event = g_value_get_boxed (param_values + 1); | ||||
|  | ||||
|   if (actor == NULL) | ||||
|     return TRUE /* stay connected */; | ||||
|  | ||||
|   /* If this event belongs to the corresponding grab for this event | ||||
|    * type then the captured-event signal won't be emitted so we have | ||||
|    * to manually forward it on */ | ||||
|  | ||||
|   switch (event->type) | ||||
|     { | ||||
|       /* Pointer events */ | ||||
|     case CLUTTER_MOTION: | ||||
|     case CLUTTER_ENTER: | ||||
|     case CLUTTER_LEAVE: | ||||
|     case CLUTTER_BUTTON_PRESS: | ||||
|     case CLUTTER_BUTTON_RELEASE: | ||||
|     case CLUTTER_SCROLL: | ||||
|       if (actor == clutter_get_pointer_grab ()) | ||||
|         event_cb (clutter_actor_get_stage (actor), | ||||
|                   event, | ||||
|                   compositor); | ||||
|       break; | ||||
|  | ||||
|       /* Keyboard events */ | ||||
|     case CLUTTER_KEY_PRESS: | ||||
|     case CLUTTER_KEY_RELEASE: | ||||
|       if (actor == clutter_get_keyboard_grab ()) | ||||
|         event_cb (clutter_actor_get_stage (actor), | ||||
|                   event, | ||||
|                   compositor); | ||||
|  | ||||
|     default: | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|   return TRUE /* stay connected */; | ||||
|   return meta_wayland_seat_handle_event (compositor->seat, event); | ||||
| } | ||||
|  | ||||
| static void | ||||
| @@ -839,7 +607,6 @@ void | ||||
| meta_wayland_init (void) | ||||
| { | ||||
|   MetaWaylandCompositor *compositor = &_meta_wayland_compositor; | ||||
|   guint event_signal; | ||||
|   MetaMonitorManager *monitors; | ||||
|   ClutterBackend *backend; | ||||
|   CoglContext *cogl_context; | ||||
| @@ -928,21 +695,6 @@ meta_wayland_init (void) | ||||
|   compositor->seat = meta_wayland_seat_new (compositor->wayland_display, | ||||
| 					    compositor->drm_fd >= 0); | ||||
|  | ||||
|   g_signal_connect (compositor->stage, | ||||
|                     "captured-event", | ||||
|                     G_CALLBACK (event_cb), | ||||
|                     compositor); | ||||
|   /* If something sets a grab on an actor then the captured event | ||||
|    * signal won't get emitted but we still want to see these events so | ||||
|    * we can update the cursor position. To make sure we see all events | ||||
|    * we also install an emission hook on the event signal */ | ||||
|   event_signal = g_signal_lookup ("event", CLUTTER_TYPE_STAGE); | ||||
|   g_signal_add_emission_hook (event_signal, | ||||
|                               0 /* detail */, | ||||
|                               event_emission_hook_cb, | ||||
|                               compositor, /* hook_data */ | ||||
|                               NULL /* data_destroy */); | ||||
|  | ||||
|   meta_wayland_init_shell (compositor); | ||||
|  | ||||
|   clutter_actor_show (compositor->stage); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user