diff options
-rw-r--r-- | configure.in | 30 | ||||
-rw-r--r-- | src/Makefile.am | 4 | ||||
-rw-r--r-- | src/common.h | 21 | ||||
-rw-r--r-- | src/devices.h | 61 | ||||
-rw-r--r-- | src/display.c | 93 | ||||
-rw-r--r-- | src/display.h | 8 | ||||
-rw-r--r-- | src/main.c | 2 | ||||
-rw-r--r-- | src/menu.c | 104 | ||||
-rw-r--r-- | src/menu.h | 16 | ||||
-rw-r--r-- | src/ui.c | 25 | ||||
-rw-r--r-- | src/ui.h | 16 | ||||
-rw-r--r-- | src/window.c | 46 | ||||
-rw-r--r-- | src/window.h | 5 |
13 files changed, 427 insertions, 4 deletions
diff --git a/configure.in b/configure.in index 9d909b0b..d3cf72e3 100644 --- a/configure.in +++ b/configure.in @@ -158,6 +158,11 @@ AC_ARG_ENABLE(shape, [disable metacity's use of the shaped window extension]),, enable_shape=auto) +AC_ARG_ENABLE(mpx, + AC_HELP_STRING([--enable-mpx], + [enable multiple-pointer xserver features]),, + enable_mpx=no) + ## try definining HAVE_BACKTRACE AC_CHECK_HEADERS(execinfo.h, [AC_CHECK_FUNCS(backtrace)]) @@ -362,6 +367,28 @@ if test "x$found_shape" = "xyes"; then AC_DEFINE(HAVE_SHAPE, , [Have the shape extension library]) fi +XINPUT_LIBS= +found_xinput=no +AC_CHECK_LIB(Xi, XGetExtensionVersion, + [AC_CHECK_HEADER(X11/extensions/XInput.h, + XINPUT_LIBS=-lXi found_xinput=yes)], + , $ALL_X_LIBS) + +if test x$enable_mpx = xno; then + found_xinput=no +fi + +if test x$enable_mpx = xyes; then + if test "$found_xinput" = "no"; then + AC_MSG_ERROR([--enable-mpx forced and XInput not found]) + exit 1 + fi +fi + +if test "x$found_xinput" = "xyes"; then + AC_DEFINE(MPX, ,[Build with multiple-pointer xserver features]) +fi + found_xkb=no AC_CHECK_LIB(X11, XkbQueryExtension, [AC_CHECK_HEADER(X11/XKBlib.h, @@ -409,7 +436,7 @@ if test "x$found_xsync" = "xyes"; then AC_DEFINE(HAVE_XSYNC, , [Have the Xsync extension library]) fi -METACITY_LIBS="$METACITY_LIBS $XSYNC_LIBS $RANDR_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" +METACITY_LIBS="$METACITY_LIBS $XSYNC_LIBS $RANDR_LIBS $XINPUT_LIBS $SHAPE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" METACITY_MESSAGE_LIBS="$METACITY_MESSAGE_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" METACITY_WINDOW_DEMO_LIBS="$METACITY_WINDOW_DEMO_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" METACITY_PROPS_LIBS="$METACITY_PROPS_LIBS $X_LIBS $X_PRE_LIBS -lX11 $X_EXTRA_LIBS" @@ -521,6 +548,7 @@ metacity-$VERSION: Xsync: ${found_xsync} Render: ${have_xrender} Xcursor: ${have_xcursor} + Multiple-pointer xserver: ${enable_mpx} " METACITY_MINOR_VERSION=metacity_minor_version diff --git a/src/Makefile.am b/src/Makefile.am index 40b349ed..c800b390 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,7 @@ metacity_SOURCES= \ core.c \ core.h \ delete.c \ + devices.h \ display.c \ display.h \ draw-workspace.c \ @@ -111,7 +112,8 @@ libmetacity_private_la_SOURCES= \ theme-parser.h \ util.c \ util.h \ - common.h + common.h \ + devices.h libmetacity_private_la_LDFLAGS = -no-undefined libmetacity_private_la_LIBADD = @METACITY_LIBS@ diff --git a/src/common.h b/src/common.h index 8bdce9d3..8571c9f3 100644 --- a/src/common.h +++ b/src/common.h @@ -69,11 +69,31 @@ typedef enum META_MENU_OP_MOVE_RIGHT = 1 << 14, META_MENU_OP_MOVE_UP = 1 << 15, META_MENU_OP_MOVE_DOWN = 1 << 16, +#ifdef MPX + META_MENU_OP_RECOVER = 1 << 17, + META_MENU_OP_CLIENT_POINTER = 1 << 18, +#else META_MENU_OP_RECOVER = 1 << 17 +#endif } MetaMenuOp; typedef struct _MetaWindowMenu MetaWindowMenu; + +#ifdef MPX +/* This was defined here so I don't need to include devices.h on this file */ +typedef struct _MetaDevInfo MetaDevInfo; + +typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu, + Display *xdisplay, + Window client_xwindow, + guint32 timestamp, + MetaMenuOp op, + int workspace, + MetaDevInfo *pointer, + gpointer data); + +#else typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu, Display *xdisplay, Window client_xwindow, @@ -81,6 +101,7 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu, MetaMenuOp op, int workspace, gpointer data); +#endif /* when changing this enum, there are various switch statements * you have to update diff --git a/src/devices.h b/src/devices.h new file mode 100644 index 00000000..10be1456 --- /dev/null +++ b/src/devices.h @@ -0,0 +1,61 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ + +/* Metacity device structures */ + +/* + * Copyright (C) 2007 Paulo Ricardo Zanoni + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + +#ifndef META_DEVICES_H +#define META_DEVICES_H + +#ifdef MPX + +#include <X11/extensions/XInput.h> + +#include "common.h" + +/* By default, the MetaDevInfo lists have size 8. Almost no client has more + * than 8 mice or keyboards... */ +/* FIXME setting this define to 1 or 2 causes memory corruption!!!! */ +#define DEFAULT_INPUT_ARRAY_SIZE 8 + +typedef struct _MetaDevices MetaDevices; +/* typedef struct _MetaDevInfo MetaDevInfo; This guy was declared at common.h */ + +struct _MetaDevInfo +{ + XDevice *xdev; + gchar *name; +}; + +struct _MetaDevices +{ + MetaDevInfo *mice; + int miceUsed; + int miceSize; + + MetaDevInfo *keyboards; + int keybsUsed; + int keybsSize; + MetaDevInfo *pairedPointers; +}; + +#endif + +#endif diff --git a/src/display.c b/src/display.c index 9a4a6bd2..e27a3271 100644 --- a/src/display.c +++ b/src/display.c @@ -798,6 +798,99 @@ meta_display_open (void) if (meta_prefs_get_compositing_manager ()) enable_compositor (display); + +#ifdef MPX + { + /* Check to see the available input devices */ + + XDeviceInfo *devsInfo, *devInfo, *auxDevsInfo, *auxDevInfo; + int howManyDevices, i, j; + + XID pDevId; + XDevice *kDev; + XDevice *open; + MetaDevices *d; + + d = &display->devices; + + /* We should register ourselves as the pairing client here, and also as + * the access control manager too. + * XXX XRegisterPairingClient, XGrabAccessControl */ + + d->mice = g_malloc(sizeof(XID) * DEFAULT_INPUT_ARRAY_SIZE); + d->keyboards = g_malloc(sizeof(XID) * DEFAULT_INPUT_ARRAY_SIZE); + d->pairedPointers = g_malloc(sizeof(XID) * DEFAULT_INPUT_ARRAY_SIZE); + + d->miceUsed = 0; + d->miceSize = DEFAULT_INPUT_ARRAY_SIZE; + d->keybsUsed = 0; + d->keybsSize = DEFAULT_INPUT_ARRAY_SIZE; + + devsInfo = XListInputDevices(display->xdisplay, &howManyDevices); + for (i = 0; i < howManyDevices; i++) + { + devInfo = &devsInfo[i]; + + if (devInfo->use == IsXExtensionKeyboard) + { + if (d->keybsUsed == d->keybsSize) + { + /* FIXME This is broken! See comment in devices.h! */ + d->keyboards = g_realloc (d->keyboards, + sizeof(XID) * (d->keybsSize + DEFAULT_INPUT_ARRAY_SIZE)); + d->pairedPointers = g_realloc(d->pairedPointers, + sizeof(XID) * (d->keybsSize + DEFAULT_INPUT_ARRAY_SIZE)); + d->keybsSize += DEFAULT_INPUT_ARRAY_SIZE; + } + + meta_warning("opening deivce id %d, name %s\n", + (int)devInfo->id, devInfo->name); /* XXX */ + kDev = XOpenDevice(display->xdisplay, devInfo->id); + d->keyboards[d->keybsUsed].xdev = kDev; + d->keyboards[d->keybsUsed].name = + g_strdup_printf("%s", devInfo->name); + + XGetPairedPointer(display->xdisplay, kDev, (int *) &pDevId); + meta_warning("opening device id %d\n", + (int)pDevId); /* XXX */ + open = XOpenDevice(display->xdisplay, pDevId); + d->pairedPointers[d->keybsUsed].xdev = open; + + /* Look in the device list for a device with the id pDevId + * and then find its name */ + auxDevsInfo = devsInfo; + for (j = 0; j < howManyDevices; j++) + { + auxDevInfo = &auxDevsInfo[j]; + if (auxDevInfo->id == pDevId) + break; + + } + d->pairedPointers[d->keybsUsed].name = + g_strdup_printf("%s", auxDevInfo->name); + d->keybsUsed++; + meta_warning(" name = %s\n", auxDevInfo->name); /* XXX */ + } + else if (devInfo->use == IsXExtensionPointer) + { + if (d->miceUsed == d->miceSize) + { + d->mice = g_realloc(d->mice, + sizeof(XID) * (d->miceSize + DEFAULT_INPUT_ARRAY_SIZE)); + d->miceSize += DEFAULT_INPUT_ARRAY_SIZE; + } + meta_warning("opening device id %d, name %s\n", + (int)devInfo->id, devInfo->name); /* XXX */ + open = XOpenDevice(display->xdisplay, devInfo->id); + d->mice[d->miceUsed].xdev = open; + d->mice[d->miceUsed].name = g_strdup_printf("%s", devInfo->name); + d->miceUsed++; + } + } + XFreeDeviceList(devsInfo); + + } +#endif /* Done opening new display */ display->display_opening = FALSE; diff --git a/src/display.h b/src/display.h index 14bd4eee..5216afef 100644 --- a/src/display.h +++ b/src/display.h @@ -37,6 +37,10 @@ #include "common.h" #include "boxes.h" +#ifdef MPX +#include "devices.h" +#endif + #ifdef HAVE_STARTUP_NOTIFICATION #include <libsn/sn.h> #endif @@ -372,6 +376,10 @@ struct _MetaDisplay #else #define META_DISPLAY_HAS_RENDER(display) FALSE #endif + +#ifdef MPX + MetaDevices devices; +#endif }; /* Xserver time can wraparound, thus comparing two timestamps needs to take @@ -246,7 +246,7 @@ main (int argc, char **argv) if (setlocale (LC_ALL, "") == NULL) meta_warning ("Locale not understood by C library, internationalization will not work\n"); - + sigemptyset (&empty_mask); act.sa_handler = SIG_IGN; act.sa_mask = empty_mask; @@ -137,11 +137,20 @@ menu_closed (GtkMenu *widget, menu = data; meta_frames_notify_menu_hide (menu->frames); +#ifdef MPX + (* menu->func) (menu, gdk_display, + menu->client_xwindow, + gtk_get_current_event_time (), + 0, 0, 0, + menu->data); + +#else (* menu->func) (menu, gdk_display, menu->client_xwindow, gtk_get_current_event_time (), 0, 0, menu->data); +#endif /* menu may now be freed */ } @@ -156,14 +165,26 @@ activate_cb (GtkWidget *menuitem, gpointer data) md = data; meta_frames_notify_menu_hide (md->menu->frames); +#ifdef MPX (* md->menu->func) (md->menu, gdk_display, md->menu->client_xwindow, gtk_get_current_event_time (), md->op, GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), "workspace")), + g_object_get_data (G_OBJECT (menuitem), "device"), md->menu->data); +#else + (* md->menu->func) (md->menu, gdk_display, + md->menu->client_xwindow, + gtk_get_current_event_time (), + md->op, + GPOINTER_TO_INT (g_object_get_data (G_OBJECT (menuitem), + "workspace")), + md->menu->data); +#endif + /* menu may now be freed */ } @@ -311,14 +332,26 @@ menu_item_new (MenuItem *menuitem, int workspace_id) } MetaWindowMenu* +#ifdef MPX meta_window_menu_new (MetaFrames *frames, MetaMenuOp ops, MetaMenuOp insensitive, + MetaDevices *devices, Window client_xwindow, unsigned long active_workspace, int n_workspaces, MetaWindowMenuFunc func, gpointer data) +#else +meta_window_menu_new (MetaFrames *frames, + MetaMenuOp ops, + MetaMenuOp insensitive, + Window client_xwindow, + unsigned long active_workspace, + int n_workspaces, + MetaWindowMenuFunc func, + gpointer data) +#endif { int i; MetaWindowMenu *menu; @@ -477,6 +510,77 @@ meta_window_menu_new (MetaFrames *frames, g_signal_connect (menu->menu, "selection_done", G_CALLBACK (menu_closed), menu); +#ifdef MPX + + { + GtkWidget *submenu; + GtkWidget *submenuitem; + + MenuItem sep = { 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }; + submenu = gtk_menu_new(); + submenuitem = menu_item_new (&sep, -1); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), submenuitem); + gtk_widget_show (submenuitem); + } + + { + /* SetClientPointer menu */ + Display *display; + + GtkWidget *submenu; + GtkWidget *submenuitem; + XID clientPtr; + + MenuItem select_client_pointer = { + 0, MENU_ITEM_NORMAL, NULL, + FALSE, N_("Select Client Pointer") + }; + + submenu = gtk_menu_new (); + submenuitem = menu_item_new (&select_client_pointer, -1); + gtk_menu_item_set_submenu (GTK_MENU_ITEM (submenuitem), submenu); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), submenuitem); + gtk_widget_show (submenuitem); + + display = gdk_x11_drawable_get_xdisplay (GTK_WIDGET (frames)->window); + + /* Someone might have changed the clientPointer! */ + XGetClientPointer(display, client_xwindow, (int *)&clientPtr); + meta_warning("my mouse is %d\n", (int) clientPtr); /* XXX */ + + for (i = 0; i < devices->miceUsed; i++) { + + MenuItem moveitem; + MenuData *md; + GtkWidget *mi; + + moveitem.type = MENU_ITEM_RADIOBUTTON; + moveitem.op = META_MENU_OP_CLIENT_POINTER; + moveitem.label = devices->mice[i].name; + meta_warning("name = %s\n", moveitem.label); + /* XXX gotta make radiobuttons appear as checked! + moveitem.checked = (clientPtr == `this guy`) ? 1 : 0; */ + mi = menu_item_new (&moveitem, i+1); + + md = g_new (MenuData, 1); + md->menu = menu; + md->op = META_MENU_OP_CLIENT_POINTER; + g_object_set_data (G_OBJECT(mi), + "device", + &devices->mice[i]); + gtk_signal_connect_full (GTK_OBJECT (mi), + "activate", + GTK_SIGNAL_FUNC (activate_cb), + NULL, + md, + g_free, FALSE, FALSE); + + gtk_menu_shell_append (GTK_MENU_SHELL (submenu), mi); + gtk_widget_show (mi); + } + } +#endif + return menu; } @@ -26,6 +26,9 @@ #include <gtk/gtk.h> #include "frames.h" +#ifdef MPX +#include "devices.h" +#endif /* Stock icons */ #define METACITY_STOCK_DELETE "metacity-delete" @@ -43,14 +46,27 @@ struct _MetaWindowMenu MetaMenuOp insensitive; }; +#ifdef MPX MetaWindowMenu* meta_window_menu_new (MetaFrames *frames, MetaMenuOp ops, MetaMenuOp insensitive, + MetaDevices *devices, Window client_xwindow, unsigned long active_workspace, int n_workspaces, MetaWindowMenuFunc func, gpointer data); + +#else +MetaWindowMenu* meta_window_menu_new (MetaFrames *frames, + MetaMenuOp ops, + MetaMenuOp insensitive, + Window client_xwindow, + unsigned long active_workspace, + int n_workspaces, + MetaWindowMenuFunc func, + gpointer data); +#endif void meta_window_menu_popup (MetaWindowMenu *menu, int root_x, int root_y, @@ -315,21 +315,46 @@ meta_ui_set_frame_title (MetaUI *ui, } MetaWindowMenu* +#ifdef MPX meta_ui_window_menu_new (MetaUI *ui, Window client_xwindow, MetaMenuOp ops, MetaMenuOp insensitive, + MetaDevices *devices, unsigned long active_workspace, int n_workspaces, MetaWindowMenuFunc func, gpointer data) + +#else +meta_ui_window_menu_new (MetaUI *ui, + Window client_xwindow, + MetaMenuOp ops, + MetaMenuOp insensitive, + unsigned long active_workspace, + int n_workspaces, + MetaWindowMenuFunc func, + gpointer data) +#endif { + +#ifdef MPX return meta_window_menu_new (ui->frames, ops, insensitive, + devices, client_xwindow, active_workspace, n_workspaces, func, data); + +#else + return meta_window_menu_new (ui->frames, + ops, insensitive, + client_xwindow, + active_workspace, + n_workspaces, + func, data); +#endif } void @@ -26,6 +26,9 @@ /* Don't include gtk.h or gdk.h here */ #include "common.h" +#ifdef MPX +#include "devices.h" +#endif #include <X11/Xlib.h> #include <X11/Xutil.h> #include <glib.h> @@ -118,14 +121,27 @@ void meta_ui_set_frame_title (MetaUI *ui, void meta_ui_repaint_frame (MetaUI *ui, Window xwindow); +#ifdef MPX MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui, Window client_xwindow, MetaMenuOp ops, MetaMenuOp insensitive, + MetaDevices *devices, unsigned long active_workspace, int n_workspaces, MetaWindowMenuFunc func, gpointer data); + +#else +MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui, + Window client_xwindow, + MetaMenuOp ops, + MetaMenuOp insensitive, + unsigned long active_workspace, + int n_workspaces, + MetaWindowMenuFunc func, + gpointer data); +#endif void meta_ui_window_menu_popup (MetaWindowMenu *menu, int root_x, int root_y, diff --git a/src/window.c b/src/window.c index fb26ae49..1d5dcc06 100644 --- a/src/window.c +++ b/src/window.c @@ -6259,6 +6259,19 @@ recalc_window_features (MetaWindow *window) */ } +#ifdef MPX +void +meta_window_set_client_pointer (Display *xdisplay, MetaWindow *window, + MetaDevInfo *dev) +{ + meta_warning("Changing client pointer to %s\n", dev->name); /* XXX */ + XSetClientPointer(xdisplay, window->xwindow, dev->xdev); + + return; +} +#endif + +#ifdef MPX static void menu_callback (MetaWindowMenu *menu, Display *xdisplay, @@ -6266,7 +6279,19 @@ menu_callback (MetaWindowMenu *menu, guint32 timestamp, MetaMenuOp op, int workspace_index, + MetaDevInfo *device, gpointer data) + +#else +static void +menu_callback (MetaWindowMenu *menu, + Display *xdisplay, + Window client_xwindow, + guint32 timestamp, + MetaMenuOp op, + int workspace_index, + gpointer data) +#endif { MetaDisplay *display; MetaWindow *window; @@ -6369,6 +6394,12 @@ menu_callback (MetaWindowMenu *menu, case META_MENU_OP_RECOVER: meta_window_shove_titlebar_onscreen (window); break; + +#ifdef MPX + case META_MENU_OP_CLIENT_POINTER: + meta_window_set_client_pointer (xdisplay, window, device); + break; +#endif case 0: /* nothing */ @@ -6515,14 +6546,27 @@ meta_window_show_menu (MetaWindow *window, return; menu = +#ifdef MPX meta_ui_window_menu_new (window->screen->ui, window->xwindow, ops, insensitive, + &window->display->devices, meta_window_get_net_wm_desktop (window), meta_screen_get_n_workspaces (window->screen), menu_callback, - NULL); + NULL); + +#else + meta_ui_window_menu_new (window->screen->ui, + window->xwindow, + ops, + insensitive, + meta_window_get_net_wm_desktop (window), + meta_screen_get_n_workspaces (window->screen), + menu_callback, + NULL); +#endif window->display->window_menu = menu; window->display->window_with_menu = window; diff --git a/src/window.h b/src/window.h index ec3d05a8..8195a65b 100644 --- a/src/window.h +++ b/src/window.h @@ -608,4 +608,9 @@ void meta_window_unset_demands_attention (MetaWindow *window); void meta_window_update_icon_now (MetaWindow *window); +#ifdef MPX +void meta_window_set_client_pointer (Display *xdisplay, MetaWindow *window, + MetaDevInfo *dev); +#endif + #endif |