From 50e482c2509992074576f3f98b02604765cbb8fb Mon Sep 17 00:00:00 2001 From: Paulo Zanoni Date: Tue, 10 Jul 2007 03:05:15 +0000 Subject: Corrected RadioButtons. Adds option to enable/disable device access to windows. Corrects a few bugs. svn path=/branches/multiple_pointer_x/; revision=3265 --- src/common.h | 39 ++++++------ src/core.c | 6 ++ src/display.c | 7 +-- src/frames.c | 2 +- src/menu.c | 186 +++++++++++++++++++++++++++++++++++++++++++++++----------- src/window.c | 64 +++++++++++++++++++- src/window.h | 2 + 7 files changed, 247 insertions(+), 59 deletions(-) diff --git a/src/common.h b/src/common.h index 8571c9f3..5501c781 100644 --- a/src/common.h +++ b/src/common.h @@ -52,28 +52,29 @@ typedef enum typedef enum { - META_MENU_OP_DELETE = 1 << 0, - META_MENU_OP_MINIMIZE = 1 << 1, - META_MENU_OP_UNMAXIMIZE = 1 << 2, - META_MENU_OP_MAXIMIZE = 1 << 3, - META_MENU_OP_UNSHADE = 1 << 4, - META_MENU_OP_SHADE = 1 << 5, - META_MENU_OP_UNSTICK = 1 << 6, - META_MENU_OP_STICK = 1 << 7, - META_MENU_OP_WORKSPACES = 1 << 8, - META_MENU_OP_MOVE = 1 << 9, - META_MENU_OP_RESIZE = 1 << 10, - META_MENU_OP_ABOVE = 1 << 11, - META_MENU_OP_UNABOVE = 1 << 12, - META_MENU_OP_MOVE_LEFT = 1 << 13, - META_MENU_OP_MOVE_RIGHT = 1 << 14, - META_MENU_OP_MOVE_UP = 1 << 15, - META_MENU_OP_MOVE_DOWN = 1 << 16, + META_MENU_OP_DELETE = 1 << 0, + META_MENU_OP_MINIMIZE = 1 << 1, + META_MENU_OP_UNMAXIMIZE = 1 << 2, + META_MENU_OP_MAXIMIZE = 1 << 3, + META_MENU_OP_UNSHADE = 1 << 4, + META_MENU_OP_SHADE = 1 << 5, + META_MENU_OP_UNSTICK = 1 << 6, + META_MENU_OP_STICK = 1 << 7, + META_MENU_OP_WORKSPACES = 1 << 8, + META_MENU_OP_MOVE = 1 << 9, + META_MENU_OP_RESIZE = 1 << 10, + META_MENU_OP_ABOVE = 1 << 11, + META_MENU_OP_UNABOVE = 1 << 12, + META_MENU_OP_MOVE_LEFT = 1 << 13, + 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_RECOVER = 1 << 17, META_MENU_OP_CLIENT_POINTER = 1 << 18, + META_MENU_OP_ALLOW_ACCESS = 1 << 19 #else - META_MENU_OP_RECOVER = 1 << 17 + META_MENU_OP_RECOVER = 1 << 17 #endif } MetaMenuOp; diff --git a/src/core.c b/src/core.c index 1454105e..4efe6798 100644 --- a/src/core.c +++ b/src/core.c @@ -481,6 +481,12 @@ meta_core_get_menu_accelerator (MetaMenuOp menu_op, { const char *name; + /* #ifdef MPX + * FIXME: + * warning: enumeration value 'META_MENU_OP_CLIENT_POINTER' not handled in + * switch. (the same for META_MENU_OP_ALLOW_DEVICES) + * #endif */ + name = NULL; switch (menu_op) diff --git a/src/display.c b/src/display.c index e27a3271..14ef5b0e 100644 --- a/src/display.c +++ b/src/display.c @@ -813,9 +813,8 @@ meta_display_open (void) d = &display->devices; - /* We should register ourselves as the pairing client here, and also as - * the access control manager too. - * XXX XRegisterPairingClient, XGrabAccessControl */ + /* We should register ourselves as the pairing client here + * XXX XRegisterPairingClient */ d->mice = g_malloc(sizeof(XID) * DEFAULT_INPUT_ARRAY_SIZE); d->keyboards = g_malloc(sizeof(XID) * DEFAULT_INPUT_ARRAY_SIZE); @@ -850,7 +849,7 @@ meta_display_open (void) d->keyboards[d->keybsUsed].name = g_strdup_printf("%s", devInfo->name); - XGetPairedPointer(display->xdisplay, kDev, (int *) &pDevId); + XGetPairedPointer(display->xdisplay, kDev, &pDevId); meta_warning("opening device id %d\n", (int)pDevId); /* XXX */ open = XOpenDevice(display->xdisplay, pDevId); diff --git a/src/frames.c b/src/frames.c index 76f80c2c..c14e73ba 100644 --- a/src/frames.c +++ b/src/frames.c @@ -594,7 +594,7 @@ meta_frames_manage_window (MetaFrames *frames, */ meta_core_grab_buttons (gdk_display, frame->xwindow); - + g_hash_table_replace (frames->frames, &frame->xwindow, frame); } diff --git a/src/menu.c b/src/menu.c index 73f40ff4..e7bc7f1c 100644 --- a/src/menu.c +++ b/src/menu.c @@ -513,18 +513,16 @@ meta_window_menu_new (MetaFrames *frames, #ifdef MPX { - GtkWidget *submenu; - GtkWidget *submenuitem; - + GtkWidget *mi; 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); + mi = menu_item_new(&sep, -1); + gtk_menu_shell_append (GTK_MENU_SHELL (menu->menu), mi); + gtk_widget_show (mi); } { /* SetClientPointer menu */ + Display *display; GtkWidget *submenu; @@ -533,7 +531,7 @@ meta_window_menu_new (MetaFrames *frames, MenuItem select_client_pointer = { 0, MENU_ITEM_NORMAL, NULL, - FALSE, N_("Select Client Pointer") + FALSE, N_("Client pointer") }; submenu = gtk_menu_new (); @@ -545,40 +543,160 @@ meta_window_menu_new (MetaFrames *frames, 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 */ + XGetClientPointer(display, client_xwindow, &clientPtr); + + for (i = 0; i < devices->miceUsed; i++) + { + + MenuItem setcpitem; + MenuData *md; + GtkWidget *mi; + + setcpitem.type = MENU_ITEM_RADIOBUTTON; + setcpitem.op = META_MENU_OP_CLIENT_POINTER; + setcpitem.label = devices->mice[i].name; + mi = menu_item_new (&setcpitem, i+1); + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), + (clientPtr == devices->mice[i].xdev->device_id) ? 1 : 0); + + 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); + } + } - for (i = 0; i < devices->miceUsed; i++) { + { + /* Enable devices menu */ + Display *display; - MenuItem moveitem; - MenuData *md; - GtkWidget *mi; + GtkWidget *submenu; + GtkWidget *submenuitem; + + int rule, nperm, ndeny, j; + XID *perm, *deny; + + int allowed; - 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); + MenuItem allowed_devices = { + 0, MENU_ITEM_NORMAL, NULL, + FALSE, N_("Allowed devices") + }; + + submenu = gtk_menu_new (); + submenuitem = menu_item_new (&allowed_devices, -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); + + /* Gotta know which device has access to the window... Currently, we're + * doing this by calling XQueryWindowAccess everytime. But maybe we could + * store information on the windows. The problem is that if a client makes a + * change, we won't be able to discover (will we? do we have an xevent for + * it?) */ + XQueryWindowAccess(display, client_xwindow, &rule, &perm, &nperm, + &deny, &ndeny); + + for (i = 0; i < devices->miceUsed; i++) + { + + /* Add the mice to the menu */ + MenuItem alwdevitem; + MenuData *md; + GtkWidget *mi; + + alwdevitem.type = MENU_ITEM_CHECKBOX; + alwdevitem.op = META_MENU_OP_ALLOW_ACCESS; + alwdevitem.label = devices->mice[i].name; + mi = menu_item_new (&alwdevitem, i+1); + allowed = 1; + for (j = 0; j < ndeny; j++) + if (devices->mice[i].xdev->device_id == deny[j] ) + allowed = 0; + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), allowed); + + md = g_new (MenuData, 1); + md->menu = menu; + md->op = META_MENU_OP_ALLOW_ACCESS; + 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); + + } + + + /* Add a separator */ + { + GtkWidget *mi; + MenuItem sep = { 0, MENU_ITEM_SEPARATOR, NULL, FALSE, NULL }; + mi = menu_item_new(&sep, -1); gtk_menu_shell_append (GTK_MENU_SHELL (submenu), mi); gtk_widget_show (mi); } + + for (i = 0; i < devices->keybsUsed; i++) + { + + /* Add the keyboards to the menu */ + MenuItem alwdevitem; + MenuData *md; + GtkWidget *mi; + + alwdevitem.type = MENU_ITEM_CHECKBOX; + alwdevitem.op = META_MENU_OP_ALLOW_ACCESS; + alwdevitem.label = devices->keyboards[i].name; + mi = menu_item_new (&alwdevitem, i+1); + + allowed = 1; + for (j = 0; j < ndeny; j++) + if (devices->keyboards[i].xdev->device_id == deny[j] ) + allowed = 0; + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (mi), allowed); + + md = g_new (MenuData, 1); + md->menu = menu; + md->op = META_MENU_OP_ALLOW_ACCESS; + g_object_set_data (G_OBJECT(mi), + "device", + &devices->keyboards[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); + + } + XFree(perm); + XFree(deny); + } + #endif return menu; diff --git a/src/window.c b/src/window.c index 1d5dcc06..3cd013e3 100644 --- a/src/window.c +++ b/src/window.c @@ -49,6 +49,10 @@ #include #include +#ifdef MPX +#include +#endif + #ifdef HAVE_SHAPE #include #endif @@ -6264,11 +6268,65 @@ 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; } + +void +meta_window_change_access (Display *xdisplay, MetaWindow *window, + MetaDevInfo *dev) +{ + + /* Metacity's behavior is: we always play with deny lists. According to + * xserver/dix/access.c:250, permit lists have priority over deny lists. So, + * if applications want to overwrite metacity's settings, they must use the + * "permit" lists. Metacity also sets NO default rule. */ + int rule, nperm, ndeny, i, allowed; + XID *perm, *deny; + + /* Read menu.c:~605 comments about calling XQueryWindowAccess evertytime */ + XQueryWindowAccess(xdisplay, window->xwindow, &rule, &perm, &nperm, &deny, + &ndeny); + + allowed = 1; + for (i = 0; i < ndeny; i++) + { + if (! allowed) + /* We already know that we are going to have to remove the device from + * the list, so let's do it now! */ + deny[i-1] = deny[i]; + if (dev->xdev->device_id == deny[i]) + allowed = 0; + } + + if (XGrabAccessControl(xdisplay)) + { + if (allowed) + { + /* Put him into the deny list! */ + /* XXX We're reallocating something allocated by xlib can't is be + * dangerous? Had no problem until now... */ + deny = (XID *) realloc (deny, sizeof(XID) * ndeny +1); + deny[ndeny] = dev->xdev->device_id; + XDenyDevices(xdisplay, window->xwindow, deny, ndeny +1); + } + else + { + /* Remove him from the deny list! */ + XDenyDevices(xdisplay, window->xwindow, deny, ndeny -1); + } + XUngrabAccessControl(xdisplay); + } + else + meta_warning("Couldn't grab access control!\n"); + + XFree(perm); /* This one can be XFree'd */ + XFree(deny); /* This one was (probably) reallocated by realloc! */ + + return; +} + #endif #ifdef MPX @@ -6399,6 +6457,10 @@ menu_callback (MetaWindowMenu *menu, case META_MENU_OP_CLIENT_POINTER: meta_window_set_client_pointer (xdisplay, window, device); break; + + case META_MENU_OP_ALLOW_ACCESS: + meta_window_change_access (xdisplay, window, device); + break; #endif case 0: diff --git a/src/window.h b/src/window.h index 8195a65b..2d2386e0 100644 --- a/src/window.h +++ b/src/window.h @@ -611,6 +611,8 @@ void meta_window_update_icon_now (MetaWindow *window); #ifdef MPX void meta_window_set_client_pointer (Display *xdisplay, MetaWindow *window, MetaDevInfo *dev); +void meta_window_change_access (Display *xdisplay, MetaWindow *window, + MetaDevInfo *dev); #endif #endif -- cgit v1.2.1