static gboolean on_key_release(ClutterActor *actor, ClutterEvent *event, MosesOverview* self) { MosesOverviewPrivate* priv = self->priv; MetaScreen* screen = meta_plugin_get_screen(priv->plugin); MetaDisplay* display = meta_screen_get_display(screen); ClutterModifierType state = clutter_event_get_state(event); g_debug("%s", __func__); if (priv->ready) { guint action = meta_display_get_keybinding_action(display, clutter_event_get_key_code(event), state); if (action == elsa_wm_get_action(ELSA_WM_PLUGIN(priv->plugin), "expose-windows")) { overview_animated_destroy(self, MOSES_OV_REASON_NORMAL, FALSE); return TRUE; } } return FALSE; }
//FIXME: actually key_release is activated even when key press (WTF). does it because I'm hold alt/super? static gboolean on_key_release(ClutterActor *actor, ClutterEvent *event, MetaSwitcher* self) { MetaSwitcherPrivate* priv = self->priv; MetaScreen* screen = meta_plugin_get_screen(priv->plugin); MetaDisplay* display = meta_screen_get_display(screen); ClutterModifierType state = clutter_event_get_state(event); guint keysym = clutter_event_get_key_symbol(event); guint action = meta_display_get_keybinding_action(display, clutter_event_get_key_code(event), state); int id = priv->selected_id; if (action == META_KEYBINDING_ACTION_SWITCH_WINDOWS) { id = (id + 1) % priv->apps->len; } else if (action == META_KEYBINDING_ACTION_SWITCH_WINDOWS_BACKWARD) { id = (priv->apps->len + id - 1) % priv->apps->len; } else if (action == META_KEYBINDING_ACTION_SWITCH_APPLICATIONS) { id = (id + 1) % priv->apps->len; } else if (action == META_KEYBINDING_ACTION_SWITCH_APPLICATIONS_BACKWARD) { id = (priv->apps->len + id - 1) % priv->apps->len; } _set_highlight(self, priv->selected_id, FALSE); _set_highlight(self, id, TRUE); g_debug("%s, key: 0x%x, action: %d, previd: %d, now: %d", __func__, keysym, action, priv->selected_id, id); priv->selected_id = id; switch(keysym) { //FIXME: do not hardcode keysyms, use action instead case CLUTTER_KEY_Super_L: case CLUTTER_KEY_Super_R: case CLUTTER_KEY_Alt_L: case CLUTTER_KEY_Alt_R: { if (priv->selected_id >= 0) { meta_window_activate(g_ptr_array_index(priv->apps, priv->selected_id), clutter_get_current_event_time()); } g_object_unref(self); } default: break; } return FALSE; }
IO_METHOD(IoClutterEvent, getKeyCode) { return IONUMBER(clutter_event_get_key_code(IOCEVENT(self))); }
/** * shell_tray_icon_click: * @icon: a #ShellTrayIcon * @event: the #ClutterEvent triggering the fake click * * Fakes a press and release on @icon. @event must be a * %CLUTTER_BUTTON_RELEASE, %CLUTTER_KEY_PRESS or %CLUTTER_KEY_RELEASE event. * Its relevant details will be passed on to the icon, but its * coordinates will be ignored; the click is * always made on the center of @icon. */ void shell_tray_icon_click (ShellTrayIcon *icon, ClutterEvent *event) { XKeyEvent xkevent; XButtonEvent xbevent; XCrossingEvent xcevent; GdkWindow *remote_window; GdkScreen *screen; int x_root, y_root; Display *xdisplay; Window xwindow, xrootwindow; ClutterEventType event_type = clutter_event_type (event); g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE || event_type == CLUTTER_KEY_PRESS || event_type == CLUTTER_KEY_RELEASE); gdk_error_trap_push (); remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket)); xwindow = GDK_WINDOW_XID (remote_window); xdisplay = GDK_WINDOW_XDISPLAY (remote_window); screen = gdk_window_get_screen (remote_window); xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen)); gdk_window_get_origin (remote_window, &x_root, &y_root); /* First make the icon believe the pointer is inside it */ xcevent.type = EnterNotify; xcevent.window = xwindow; xcevent.root = xrootwindow; xcevent.subwindow = None; xcevent.time = clutter_event_get_time (event); xcevent.x = gdk_window_get_width (remote_window) / 2; xcevent.y = gdk_window_get_height (remote_window) / 2; xcevent.x_root = x_root + xcevent.x; xcevent.y_root = y_root + xcevent.y; xcevent.mode = NotifyNormal; xcevent.detail = NotifyNonlinear; xcevent.same_screen = True; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); /* Now do the click */ if (event_type == CLUTTER_BUTTON_RELEASE) { xbevent.window = xwindow; xbevent.root = xrootwindow; xbevent.subwindow = None; xbevent.time = xcevent.time; xbevent.x = xcevent.x; xbevent.y = xcevent.y; xbevent.x_root = xcevent.x_root; xbevent.y_root = xcevent.y_root; xbevent.state = clutter_event_get_state (event); xbevent.same_screen = True; xbevent.type = ButtonPress; xbevent.button = clutter_event_get_button (event); XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); xbevent.type = ButtonRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); } else { xkevent.window = xwindow; xkevent.root = xrootwindow; xkevent.subwindow = None; xkevent.time = xcevent.time; xkevent.x = xcevent.x; xkevent.y = xcevent.y; xkevent.x_root = xcevent.x_root; xkevent.y_root = xcevent.y_root; xkevent.state = clutter_event_get_state (event); xkevent.same_screen = True; xkevent.keycode = clutter_event_get_key_code (event); xkevent.type = KeyPress; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent); if (event_type == CLUTTER_KEY_RELEASE) { /* If the application takes a grab on KeyPress, we don't * want to send it a KeyRelease. There's no good way of * knowing whether a tray icon will take a grab, so just * assume it does, and don't send the KeyRelease. That might * make the tracking for key events messed up if it doesn't take * a grab, but the tray icon won't get key focus in normal cases, * so let's hope this isn't too damaging... */ xkevent.type = KeyRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent); } } /* And move the pointer back out */ xcevent.type = LeaveNotify; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); gdk_error_trap_pop_ignored (); }
/** * shell_tray_icon_click: * @icon: a #ShellTrayIcon * @event: the #ClutterEvent triggering the fake click * * Fakes a press and release on @icon. @event must be a * %CLUTTER_BUTTON_RELEASE event. Its relevant details will be passed * on to the icon, but its coordinates will be ignored; the click is * always made on the center of @icon. */ void shell_tray_icon_click (ShellTrayIcon *icon, ClutterEvent *event) { XKeyEvent xkevent; XButtonEvent xbevent; XCrossingEvent xcevent; GdkWindow *remote_window; GdkScreen *screen; int x_root, y_root; Display *xdisplay; Window xwindow, xrootwindow; ClutterEventType event_type = clutter_event_type (event); g_return_if_fail (event_type == CLUTTER_BUTTON_RELEASE || event_type == CLUTTER_KEY_RELEASE); gdk_error_trap_push (); remote_window = gtk_socket_get_plug_window (GTK_SOCKET (icon->priv->socket)); xwindow = GDK_WINDOW_XID (remote_window); xdisplay = GDK_WINDOW_XDISPLAY (remote_window); screen = gdk_window_get_screen (remote_window); xrootwindow = GDK_WINDOW_XID (gdk_screen_get_root_window (screen)); gdk_window_get_origin (remote_window, &x_root, &y_root); /* First make the icon believe the pointer is inside it */ xcevent.type = EnterNotify; xcevent.window = xwindow; xcevent.root = xrootwindow; xcevent.subwindow = None; xcevent.time = clutter_event_get_time (event); xcevent.x = gdk_window_get_width (remote_window) / 2; xcevent.y = gdk_window_get_height (remote_window) / 2; xcevent.x_root = x_root + xcevent.x; xcevent.y_root = y_root + xcevent.y; xcevent.mode = NotifyNormal; xcevent.detail = NotifyNonlinear; xcevent.same_screen = True; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); /* Now do the click */ if (event_type == CLUTTER_BUTTON_RELEASE) { xbevent.window = xwindow; xbevent.root = xrootwindow; xbevent.subwindow = None; xbevent.time = xcevent.time; xbevent.x = xcevent.x; xbevent.y = xcevent.y; xbevent.x_root = xcevent.x_root; xbevent.y_root = xcevent.y_root; xbevent.state = clutter_event_get_state (event); xbevent.same_screen = True; xbevent.type = ButtonPress; xbevent.button = clutter_event_get_button (event); XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); xbevent.type = ButtonRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xbevent); } else { xkevent.window = xwindow; xkevent.root = xrootwindow; xkevent.subwindow = None; xkevent.time = xcevent.time; xkevent.x = xcevent.x; xkevent.y = xcevent.y; xkevent.x_root = xcevent.x_root; xkevent.y_root = xcevent.y_root; xkevent.state = clutter_event_get_state (event); xkevent.same_screen = True; xkevent.type = KeyPress; xkevent.keycode = clutter_event_get_key_code (event); XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent); xkevent.type = KeyRelease; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xkevent); } /* And move the pointer back out */ xcevent.type = LeaveNotify; XSendEvent (xdisplay, xwindow, False, 0, (XEvent *)&xcevent); gdk_error_trap_pop_ignored (); }