Compare commits

...

76 Commits

Author SHA1 Message Date
052e8cc8e2 frame: disallow frame operations if the popup is open
If some device has a popped up menu, meta_frame_get_flags()
returns 0 to indicate other devices cannot trigger any
actions on the frame.
2012-11-03 19:47:37 -04:00
827999aa82 ui: Add a MetaDevice arg to meta_window_menu_popup()
This will be the device popping up the menu, gtk_menu_popup()
uses the current GTK+ event device, and that might not even be
filled up with mutter event bypassing.
2012-11-03 19:47:37 -04:00
54a58bd9b8 window: Make MetaWindow keep a pointer to the popup menu
Multiple windows may now have different popup menus, responding
only to the device pair that popped it up.
2012-11-03 19:47:37 -04:00
dc29985b80 ui: enable multidevice on frame windows
This is so different pointers may have different
cursors on them.
2012-11-03 19:47:37 -04:00
acbd4bf599 frames: Use the triggering device when updating controls 2012-11-03 19:47:37 -04:00
b742d1bc64 frames: Get coordinates from event
Don't spare a synchronous X call, instead translate
properly the XEvent coordinates in ui.c and use
the event coordinates in MetaFrames
2012-11-03 19:47:37 -04:00
ae1290e3b4 display: Make focus info persistent
It must not be freed (at least meanwhile the device pair
exists), so ensure it's kept around, and we don't create
info for a same keyboard twice.
2012-11-03 19:47:37 -04:00
8037cc5ec4 window: make guess_grab_pointer() more reliable
Now either the current focus keyboard or the client pointer
(i.e. the pointer paired to the last keyboard that had the
window focus) are used to guess the pointer that should be
grabbed.
2012-11-03 19:47:36 -04:00
275ab901b0 window: set the corresponding client pointer on focused windows.
The client window determines the device pair that is used for
core protocol calls such as XQueryPointer(), so different
clients using the core protocol can be focused by different
devices simultaneously.
2012-11-03 19:47:36 -04:00
b3a9d1b39a core: enable XInput2 by default
This is nothing but the beginning, things work with a single
pointer/keyboard pair, but will be largely broken with multiple
devices interacting simultaneously, so we first need a policy
to establish a sensible behavior for extra pointer/keyboard
pairs.

the MUTTER_USE_CORE_DEVICES envvar has been added to force use
of Xlib core events for devices in order to check for regressions.
2012-11-03 19:47:36 -04:00
ac187476ae xi2: Workaround some bugs in XI2 passive grabs
XIAllMasterDevices doesn't quite work for key grabs, so only do
this at the moment for the Virtual Core Keyboard
2012-11-03 19:47:36 -04:00
f512da8c47 display: Ignore events from slave devices
Mutter only handles master devices.
2012-11-03 19:47:36 -04:00
2b47bffbee compositor: use meta_device_grab() for pointer/keyboard grabs
These happen invariably on the VCP/VCK pair.
2012-11-03 19:47:36 -04:00
8da5a01c92 screen: Use meta_device_pointer_set_window_cursor() for startup sequence.
At the moment feedback is only provided for the Virtual Core Pointer
2012-11-03 19:47:36 -04:00
25dc04440b device-map: Add meta_device_map_list_devices()
This function returns a list of the devices currently handled by
the device map.
2012-11-03 19:47:36 -04:00
7138cc7ea4 core: Make frame handle per-pointer cursors. 2012-11-03 19:47:36 -04:00
04cbdb4e23 workspace: use triggering device to focus the default window on workspace switch 2012-11-03 19:47:36 -04:00
e138726ded screen: make "monitor under pointer" logic work for several devices 2012-11-03 19:47:36 -04:00
84dfc98636 window: query the guessed pointer's modifiers on _NET_WM_MOVERESIZE 2012-11-03 19:47:36 -04:00
95247457ef display: Use the grab pointer for delayed window raising 2012-11-03 19:47:35 -04:00
9b1b7b71e2 keybindings: use the right device for querying the modifier mask. 2012-11-03 19:47:35 -04:00
4facab385d devices: make meta_device_pointer_query_position() return a boolean
like in XQueryPointer/XIQueryPointer, the return value tells whether
the pointer device is on the same screen than the passed window.
2012-11-03 19:47:35 -04:00
cc6dba2113 display: Update mouse mode focus code for XI2 2012-11-03 19:47:35 -04:00
5f6f67fb4e core: Make keyboard focus handling happen per-keyboard
MetaFocusInfo is a struct holding all necessary info, code has
been updated to use the per-keyboard focus info instead of the
old fields.
2012-11-03 19:47:35 -04:00
0d97e6adeb core: Add meta_device_keyboard_[gs]et_focus_window()
These functions are meant to replace X[GS]etInputFocus() calls across
the core.
2012-11-03 19:47:35 -04:00
991fdeb9dd display: Use meta_device_grab() for pointer active grabs. 2012-11-03 19:47:35 -04:00
df908e5256 keybindings: Use meta_device_grab() for keyboard active grabs 2012-11-03 19:47:35 -04:00
4b88c1c72a window: Use meta_device_pointer_warp() 2012-11-03 19:47:35 -04:00
33d4732bde core: Keep track of per pointer/keyboard grabs
There is now a MetaGrabInfo struct, holding all information about
an ongoing grab, there were unfortunately no means of making this
commit smaller, as things are too intertwined to separate it,

On places where it was most obvious, the correct device has been
used (in reaction to events, for example), in other parts, the
private API has been extended to include the MetaDevice (or device
ID for core.h functions), in other places, the virtual core
pointer/keyboard are used out of cluelessness.
2012-11-03 19:47:35 -04:00
2bbd82ba51 ui: Use input-events.h to translate XEvents to GdkEvents
This is the only use in the UI part of core functions not
exported via core.h, but this is sort of a hack within a hack,
and still better than doing the XInput2 vs core dance again.
2012-11-03 19:47:35 -04:00
13acafabe2 devices: Make MetaDevice/MetaDeviceMap partly public
MetaDevice is quite limited outside of the core, mostly useful
to represent a device, and get the paired one.
2012-11-03 19:47:34 -04:00
20537b9bb0 keybindings: Replace XGrabKey() with meta_device_map_grab_key() 2012-11-03 19:47:34 -04:00
373ef2e6f1 display: Replace XGrabButton with meta_device_map_grab_button() 2012-11-03 19:47:34 -04:00
93c7a22161 core: Add XInput2 device map implementation 2012-11-03 19:47:34 -04:00
9f06372e17 Replace XAllowEvents with meta_device_allow_events() 2012-11-03 19:37:53 -04:00
b3ecd268f6 Use meta_core_select_events() for input events 2012-11-03 19:37:52 -04:00
c32ee410e9 core: Add method to select events on a window
This function handles XInput2 vs core in input events.
2012-11-03 19:37:52 -04:00
3584f38d08 devices-xi2: Export function to translate event mask 2012-11-03 19:37:52 -04:00
712d2feb73 Add XInput2 input devices implementation 2012-11-03 19:37:52 -04:00
7b21bd8c6f window: use input event helper functions in grab operations. 2012-11-03 19:37:52 -04:00
c7c1053ade input-events: Add method to get the device for an event 2012-11-03 19:37:52 -04:00
d7bd7c9a40 core: Add device map object
It will contain the input devices available
2012-11-03 19:37:52 -04:00
96cdedf569 core: Add core devices implementation 2012-11-03 19:37:52 -04:00
8865578933 device: Add methods to pair devices 2012-11-03 19:37:52 -04:00
1a29f2cd0f Add pointer/keyboard abstract classes 2012-11-03 19:37:52 -04:00
324d9fdb14 compositor: Use helper functions for input events 2012-11-03 19:37:52 -04:00
190037cd72 keybindings: Use input event helper functions 2012-11-03 19:37:52 -04:00
a3ca52bf0f window: use input event helper functions on notify_focus() 2012-11-03 19:37:51 -04:00
29b5fd7fd7 display: get crossing/focus events details via helper functions 2012-11-03 19:37:51 -04:00
7a3d49b88e display: get button event coordinates with the helper functions 2012-11-03 19:37:51 -04:00
3e3ad71a68 display: get button events state from helper functions 2012-11-03 19:37:51 -04:00
1c3b695848 display: get button number from helper input event function 2012-11-03 19:37:51 -04:00
e1379441d4 display: Use helper function to get input events' timestamp 2012-11-03 19:37:51 -04:00
d75f43f504 display: Use helper functions for getting window/root in input events 2012-11-03 19:37:51 -04:00
de6dceb3ac display: Get the right window/time for input events 2012-11-03 19:37:51 -04:00
03ddc0cd94 display: separate input/non-input events handling in the event callback
We now use meta_input_event_get_type() to discern input events from the
others. This commit has involved plenty of indenting changes, so it's
better seen with git diff -b.
2012-11-03 19:37:51 -04:00
f440af2c02 core: Add helper code to handle input events
These will be used with every input event out there so they're
dealt with uniformly.
2012-11-03 19:37:51 -04:00
8b3ef16460 display: Add XInput2 variables in private struct 2012-11-03 19:37:51 -04:00
7d587770f3 configure: Check for XInput2 2012-11-03 19:37:51 -04:00
188d532438 display: Ignore DamageNotify in spew 2012-11-03 19:37:51 -04:00
f258556cec MetaPluginManager: don't send events to Clutter twice
When support for multiple plugins was removed, the logic that was
supposed to send events to Clutter directly *only if there is no filter
function from a plugin* was broken, so events were being sent to
Clutter twice if Clutter didn't consume them the first time.

https://bugzilla.gnome.org/show_bug.cgi?id=686406
2012-11-03 19:36:41 -04:00
62dbaa89ca mutter: Don't call g_type_init
It has been deprecated upstream.
2012-11-02 11:45:11 -04:00
b56396eca5 Updated German translation 2012-10-30 18:59:33 +01:00
0fdc36cac4 Updated Brazilian Portuguese Translation 2012-10-29 16:29:49 -02:00
2cc0d31b17 window: Avoid spurious focus-window changes when showing desktop
When using the show-desktop shortcut with no desktop window, unshowing
will focus the second-most-recently-used window. If we find a desktop
window, it will be focused explicitly and everything works as expected;
however without a desktop window, we end up hiding the focus window,
which will use focus_default_window() with the not_this_one parameter
to move focus away. We used to get away with this, as the not_this_one
parameter was ignored until commit e257580b94, now with bug 675982
fixed, we need to explicitly handle the show-desktop case.

https://bugzilla.gnome.org/show_bug.cgi?id=686928
2012-10-26 15:52:32 +02:00
e2bf91cd61 Bump version to 3.7.1
Update NEWS
2012-10-23 14:50:37 +02:00
294311b2d1 [l10n] Updated Estonian translation 2012-10-22 22:02:58 +03:00
db6d89b742 Updated Norwegian bokmål translation 2012-10-22 19:52:14 +02:00
2717a02a8d screen: Ignore num-workspaces when using dynamic workspaces
On startup, workspaces are initialized according to the num-workspaces
preference. However when using dynamic workspaces, the actual number
of workspaces in use might be greater than the preference (when
replacing the window manager), forcing windows on those workspaces
to the first workspace.
To fix, ignore the preference completely when using dynamic workspaces
and try to restore the previous number of workspaces (as read from
_NET_NUMBER_OF_DESKTOPS).

https://bugzilla.gnome.org/show_bug.cgi?id=685439
2012-10-17 22:43:26 +02:00
4344c9e192 Updated Serbian translation 2012-10-17 10:11:38 +02:00
53e2d34628 Updated Czech translation 2012-10-17 08:27:39 +02:00
c602d53649 Updated Indonesian translation 2012-10-16 23:42:05 +07:00
43a121c8d9 Updated Spanish translation 2012-10-16 18:12:08 +02:00
a8c5100fbb Updated Galician translations 2012-10-16 17:06:40 +02:00
5034bd8a7e Updated Slovenian translation 2012-10-16 15:33:58 +02:00
07d8b9ce19 Revert "delete: Unbreak string freeze"
This reverts commit 09713c5fd4.

https://bugzilla.gnome.org/show_bug.cgi?id=684306
2012-10-16 14:47:37 +02:00
76 changed files with 7644 additions and 2659 deletions

12
NEWS
View File

@ -1,3 +1,15 @@
3.7.1
=====
* screen: Ignore num-workspaces when using dynamic workspaces [Florian; #685439]
Contributors:
Florian Müllner
Translations:
Mattias Põldaru [et], Kjartan Maraas [nb], Мирослав Николић [sr, sr@latin],
Marek Černocký [cs], Andika Triwidada [id], Daniel Mustieles [es],
Fran Diéguez [gl], Matej Urbančič [sl]
3.6.1
=====
* Fix crash when opening large popup menus [Jasper; #681676]

View File

@ -1,7 +1,7 @@
AC_PREREQ(2.50)
m4_define([mutter_major_version], [3])
m4_define([mutter_minor_version], [6])
m4_define([mutter_minor_version], [7])
m4_define([mutter_micro_version], [1])
m4_define([mutter_version],
@ -199,6 +199,33 @@ if test x$have_xcursor = xyes; then
AC_DEFINE(HAVE_XCURSOR, , [Building with Xcursor support])
fi
XINPUT2_VERSION=1.4.0
AC_ARG_ENABLE(xinput2,
AC_HELP_STRING([--disable-xinput2],
[disable XInput2 usage]),,
enable_xinput2=yes)
if test x$enable_xinput2 = xyes; then
AC_MSG_CHECKING([XInput2])
if $PKG_CONFIG --atleast-version $XINPUT2_VERSION xi; then
have_xinput2=yes
else
have_xinput2=no
fi
AC_MSG_RESULT($have_xinput2)
else
have_xinput2=no
fi
if test x$have_xinput2 = xyes; then
echo "Building with XInput2"
MUTTER_PC_MODULES="$MUTTER_PC_MODULES xi"
AC_DEFINE(HAVE_XINPUT2, , [Building with XInput2 support])
fi
AM_CONDITIONAL(HAVE_XINPUT2, test "$have_xinput2" = "yes")
PKG_CHECK_MODULES(MUTTER, $MUTTER_PC_MODULES)
# This is used for plugins
@ -468,6 +495,7 @@ mutter-$VERSION
Shape extension: ${found_shape}
Xsync: ${found_xsync}
Xcursor: ${have_xcursor}
XInput2: ${have_xinput2}
"

View File

@ -14,9 +14,9 @@ msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-08-06 23:35+0000\n"
"POT-Creation-Date: 2012-10-16 12:48+0000\n"
"PO-Revision-Date: 2012-03-26 02:24+0200\n"
"Last-Translator: Petr Kovar <pknbe@volny.cz>\n"
"Last-Translator: Marek Černocký <marek@manet.cz>\n"
"Language-Team: Czech <gnome-cs-list@gnome.org>\n"
"Language: cs\n"
"MIME-Version: 1.0\n"
@ -55,16 +55,16 @@ msgstr "Událost zvonku"
msgid "Unknown window information request: %d"
msgstr "Neznámý informační požadavek okna: %d"
#: ../src/core/delete.c:114
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "%s nereaguje."
msgid "%s is not responding."
msgstr "%s nereaguje."
#: ../src/core/delete.c:118
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "Aplikace nereaguje."
#: ../src/core/delete.c:123
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -72,25 +72,25 @@ msgstr ""
"Je možné chvíli počkat, aby aplikace mohla pokračovat, nebo si vynutit úplné "
"ukončení aplikace."
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Počkat"
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Vynutit ukončení"
#: ../src/core/display.c:380
#: ../src/core/display.c:396
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Schází rozšíření %s vyžadované funkcemi kompozitoru"
#: ../src/core/display.c:446
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nelze otevřít displej X Window System „%s“\n"
#: ../src/core/keybindings.c:844
#: ../src/core/keybindings.c:853
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -159,7 +159,7 @@ msgstr "Vypíše verzi"
msgid "Mutter plugin to use"
msgstr "Zásuvný modul Mutter, který se má použít"
#: ../src/core/prefs.c:1065
#: ../src/core/prefs.c:1079
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -167,12 +167,12 @@ msgstr ""
"Bylo zakázáno obcházení chyb aplikací. Některé aplikace se možná nebudou "
"chovat správně.\n"
#: ../src/core/prefs.c:1140
#: ../src/core/prefs.c:1154
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Nelze zpracovat popis písma „%s“ v klíči GSettings %s\n"
#: ../src/core/prefs.c:1206
#: ../src/core/prefs.c:1220
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -181,7 +181,7 @@ msgstr ""
"„%s“ nalezené v databázi nastavení není platnou hodnotou modifikátoru "
"tlačítka myši\n"
#: ../src/core/prefs.c:1724
#: ../src/core/prefs.c:1747
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -190,7 +190,7 @@ msgstr ""
"„%s“ nalezené v databázi nastavení není platnou hodnotou klávesové zkratky "
"„%s“\n"
#: ../src/core/prefs.c:1821
#: ../src/core/prefs.c:1844
#, c-format
msgid "Workspace %d"
msgstr "Plocha %d"
@ -317,7 +317,7 @@ msgid "Window manager error: "
msgstr "Chyba správce oken: "
#. first time through
#: ../src/core/window.c:7234
#: ../src/core/window.c:7237
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -333,7 +333,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:7899
#: ../src/core/window.c:7902
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -343,22 +343,22 @@ msgstr ""
"velikost, ale nastavuje min. velikost %d × %d a max. velikost %d × %d; to "
"nedává smysl.\n"
#: ../src/core/window-props.c:310
#: ../src/core/window-props.c:274
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Aplikace nastavila neplatný _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:429
#: ../src/core/window-props.c:393
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1484
#: ../src/core/window-props.c:1448
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Neplatné okno WM_TRANSIENT_FOR 0x%lx specifikováno pro %s.\n"
#: ../src/core/window-props.c:1495
#: ../src/core/window-props.c:1459
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "Okno WM_TRANSIENT_FOR 0x%lx by vytvořilo smyčku pro %s.\n"
@ -477,10 +477,24 @@ msgstr ""
"při procházení okny."
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr "Se změnou zaměření čekat na zastavení pohybu ukazatele"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Je-li je zapnuto a režim zaměření je buď „sloppy“ nebo „mouse“, pak se "
"zaměření nezmění hned, když vstoupíte do kona, ale až se přestane pohybovat "
"ukazatel."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
msgstr "Šířka přetažitelného okraje"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
msgid ""
"The amount of total draggable borders. If the theme's visible borders are "
"not enough, invisible borders will be added to meet this value."
@ -488,11 +502,11 @@ msgstr ""
"Počet všech přetažitelných okrajů. Nestačí-li viditelné okraje motivu, budou "
"přidány neviditelné okraje, aby bylo docíleno zadané hodnoty."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Select window from tab popup"
msgstr "Vybrat okno z překryvné nabídky tabulátoru"
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
#: ../src/org.gnome.mutter.gschema.xml.in.h:18
msgid "Cancel tab popup"
msgstr "Zrušit překryvné okno tabulátoru"

View File

@ -13,8 +13,8 @@ msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-09-06 16:35+0000\n"
"PO-Revision-Date: 2012-09-06 21:22+0200\n"
"POT-Creation-Date: 2012-10-22 19:35+0000\n"
"PO-Revision-Date: 2012-10-26 08:14+0200\n"
"Last-Translator: Tobias Endrigkeit <tobiasendrigkeit@googlemail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
@ -56,16 +56,16 @@ msgstr "Klangereignis"
msgid "Unknown window information request: %d"
msgstr "Unbekannte Fensterinformation angefordert: %d"
#: ../src/core/delete.c:114
#: ../src/core/delete.c:113
#, c-format
msgid "%s is not responding."
msgstr "%s antwortet nicht."
#: ../src/core/delete.c:118
#: ../src/core/delete.c:117
msgid "Application is not responding."
msgstr "Die Anwendung antwortet nicht."
#: ../src/core/delete.c:123
#: ../src/core/delete.c:122
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -73,20 +73,20 @@ msgstr ""
"Sie können der Anwendung noch etwas Zeit geben oder ein sofortiges Beenden "
"erzwingen."
#: ../src/core/delete.c:130
#: ../src/core/delete.c:129
msgid "_Wait"
msgstr "_Warten"
#: ../src/core/delete.c:130
#: ../src/core/delete.c:129
msgid "_Force Quit"
msgstr "_Beenden erzwingen"
#: ../src/core/display.c:380
#: ../src/core/display.c:396
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Die für Compositing benötigte %s-Erweiterung wurde nicht gefunden"
#: ../src/core/display.c:446
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n"
@ -163,7 +163,7 @@ msgstr "Version ausgeben"
msgid "Mutter plugin to use"
msgstr "Zu benutzendes Mutter-Plugin"
#: ../src/core/prefs.c:1071
#: ../src/core/prefs.c:1079
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -171,14 +171,14 @@ msgstr ""
"Provisorien (Workarounds) für defekte Anwendungen abgeschaltet. "
"Möglicherweise funktionieren manche Anwendungen nicht richtig.\n"
#: ../src/core/prefs.c:1146
#: ../src/core/prefs.c:1154
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr ""
"Schriftbeschreibung »%s« aus GConf-Schlüssel %s konnte nicht verarbeitet "
"werden\n"
#: ../src/core/prefs.c:1212
#: ../src/core/prefs.c:1220
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -187,7 +187,7 @@ msgstr ""
"In der Konfigurationsdatenbank gefundenes »%s« ist kein zulässiger Wert für "
"den Maustastenumschalter\n"
#: ../src/core/prefs.c:1736
#: ../src/core/prefs.c:1747
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -196,7 +196,7 @@ msgstr ""
"In der Konfigurationsdatenbank gefundenes »%s« ist kein zulässiger Wert für "
"die Tastenkombination »%s«\n"
#: ../src/core/prefs.c:1833
#: ../src/core/prefs.c:1844
#, c-format
msgid "Workspace %d"
msgstr "Arbeitsfläche %d"
@ -328,7 +328,7 @@ msgid "Window manager error: "
msgstr "Fensterverwalter-Fehler:"
#. first time through
#: ../src/core/window.c:7234
#: ../src/core/window.c:7237
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -350,7 +350,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:7899
#: ../src/core/window.c:7902
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -360,22 +360,22 @@ msgstr ""
"veränderbar ist, setzt jedoch die minimale Größe auf %d x %d und die "
"maximale Größe auf %d x %d; dies ergibt keinen Sinn.\n"
#: ../src/core/window-props.c:310
#: ../src/core/window-props.c:274
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Anwendung hat eine unsinnige _NET_WM_PID %lu angegeben\n"
#: ../src/core/window-props.c:429
#: ../src/core/window-props.c:393
#, c-format
msgid "%s (on %s)"
msgstr "%s (auf %s)"
#: ../src/core/window-props.c:1484
#: ../src/core/window-props.c:1448
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Ungültiges WM_TRANSIENT_FOR-Fenster 0x%lx festgelegt für %s.\n"
#: ../src/core/window-props.c:1495
#: ../src/core/window-props.c:1459
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr ""
@ -501,11 +501,25 @@ msgstr ""
"Hervorhebung des Rahmens deaktiviert werden soll."
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr "Fokus-Änderungen verzögern, bis der Zeiger aufhört sich zu bewegen"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Falls dieser Schlüssel gesetzt ist und der Fokusmodus entweder »sloppy« oder "
"»mouse« ist, wird der Fokus nicht sofort beim Erreichen eines Fensters "
"geändert, sondern erst, wenn der Zeiger aufhört sich zu bewegen."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
msgstr "Breite der ziehbaren Ränder"
# Lange Beschreibung von »Draggable border width«
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
msgid ""
"The amount of total draggable borders. If the theme's visible borders are "
"not enough, invisible borders will be added to meet this value."
@ -514,11 +528,11 @@ msgstr ""
"nicht ausreichen, werden unsichtbare Ränder hinzugefügt, um diesen Wert zu "
"erreichen."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Select window from tab popup"
msgstr "Fenster aus Tab-Anzeige auswählen"
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
#: ../src/org.gnome.mutter.gschema.xml.in.h:18
msgid "Cancel tab popup"
msgstr "Tab-Anzeige abbrechen"

492
po/es.po
View File

@ -14,15 +14,15 @@ msgstr ""
"Project-Id-Version: mutter.master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-10-11 14:32+0000\n"
"PO-Revision-Date: 2012-10-13 12:20+0200\n"
"POT-Creation-Date: 2012-10-16 12:48+0000\n"
"PO-Revision-Date: 2012-10-16 18:11+0200\n"
"Last-Translator: Daniel Mustieles <daniel.mustieles@gmail.com>\n"
"Language-Team: Español; Castellano <gnome-es-list@gnome.org>\n"
"Language-Team: Español <gnome-es-list@gnome.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"Plural-Forms: nplurals=2; plural=(n!=1);\n"
"X-Generator: Gtranslator 2.91.5\n"
#: ../src/50-mutter-windows.xml.in.h:1
@ -45,8 +45,8 @@ msgid ""
"Another compositing manager is already running on screen %i on display \"%s"
"\"."
msgstr ""
"Ya existe un gestor de composición ejecutándose en la monitor %i, pantalla "
"«%s»."
"Ya existe un gestor de composición ejecutándose en la monitor %i, pantalla «%"
"s»."
#: ../src/core/bell.c:320
msgid "Bell event"
@ -57,16 +57,17 @@ msgstr "Evento de campana"
msgid "Unknown window information request: %d"
msgstr "Petición de información de ventana desconocida: %d"
#: ../src/core/delete.c:113
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "%s no está respondiendo."
#| msgid "%s is not responding."
msgid "%s” is not responding."
msgstr "«%s» no está respondiendo."
#: ../src/core/delete.c:117
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "La aplicación no está respondiendo."
#: ../src/core/delete.c:122
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -74,11 +75,11 @@ msgstr ""
"Puede elegir esperar un rato para ver si continua o forzar la aplicación "
"para cerrarla completamente."
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Esperar"
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Forzar la salida"
@ -87,7 +88,7 @@ msgstr "_Forzar la salida"
msgid "Missing %s extension required for compositing"
msgstr "Falta la extensión %s requerida para la composición"
#: ../src/core/display.c:492
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Ocurrió un error al abrir la pantalla de X Window System «%s»\n"
@ -344,8 +345,8 @@ msgstr ""
#: ../src/core/window.c:7902
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
"%d x %d and max size %d x %d; this doesn't make much sense.\n"
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size %"
"d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr ""
"La ventana %s ha establecido la propiedad MWM indicando que no es "
"redimensionable, pero configuró el tamaño mínimo a %d x %d y el tamaño "
@ -416,10 +417,10 @@ msgid ""
"\"Windows key\" on PC hardware. It's expected that this binding either the "
"default or set to the empty string."
msgstr ""
"Esta clave iniciará el «revestimiento» («overlay»), que es una combinación "
"de vista general de la ventana y el sistema de lanzamiento de aplicaciones. "
"Lo predeterminado está pensado para la «tecla de Windows». Se espera que "
"esta combinación de tecla sea la predeterminada o se establezca a una cadena "
"Esta clave iniciará el «revestimiento» («overlay»), que es una combinación de "
"vista general de la ventana y el sistema de lanzamiento de aplicaciones. Lo "
"predeterminado está pensado para la «tecla de Windows». Se espera que esta "
"combinación de tecla sea la predeterminada o se establezca a una cadena "
"vacía."
#: ../src/org.gnome.mutter.gschema.xml.in.h:3
@ -496,19 +497,14 @@ msgid "Delay focus changes until the pointer stops moving"
msgstr "Retrasar el cambio de foco hasta detener el puntero"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
#| msgid ""
#| "If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
#| "the focused window will be automatically raised after a delay specified "
#| "by the auto_raise_delay key. This is not related to clicking on a window "
#| "to raise it, nor to entering a window during drag-and-drop."
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Si está establecido a «true» y el modo del foco es «sloppy» o «mouse» "
"entonces el foco no se cambiará inmediatamente al entrar en una ventana, "
"pero sí después de dejar quieto el puntero."
"Si está establecido a «true» y el modo del foco es «sloppy» o «mouse» entonces "
"el foco no se cambiará inmediatamente al entrar en una ventana, pero sí "
"después de dejar quieto el puntero."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
@ -792,8 +788,8 @@ msgid ""
"Invalid character '%c' in color_name parameter of gtk:custom, only A-Za-z0-9-"
"_ are valid"
msgstr ""
"Caracter «%c» no válido en el parámetro «color_name» de «gtk:custom», sólo "
"«A-Za-z0-9-_» son válidos"
"Caracter «%c» no válido en el parámetro «color_name» de «gtk:custom», sólo «A-Za-"
"z0-9-_» son válidos"
#: ../src/ui/theme.c:1231
#, c-format
@ -859,8 +855,8 @@ msgstr "El valor alfa «%s» en el color mezclado no está entre 0.0 y 1.0"
msgid ""
"Shade format is \"shade/base_color/factor\", \"%s\" does not fit the format"
msgstr ""
"El formato de sombreado es «shade/base_color/factor», «%s» no coincide con "
"el formato"
"El formato de sombreado es «shade/base_color/factor», «%s» no coincide con el "
"formato"
#: ../src/ui/theme.c:1422
#, c-format
@ -1025,8 +1021,8 @@ msgid ""
"No frame style set for window type \"%s\" in theme \"%s\", add a <window "
"type=\"%s\" style_set=\"whatever\"/> element"
msgstr ""
"No hay un estilo de marco para el tipo de ventana «%s» en el tema «%s», "
"añada un elemento <window type=\"%s\" style_set=\"whatever\"/>"
"No hay un estilo de marco para el tipo de ventana «%s» en el tema «%s», añada "
"un elemento <window type=\"%s\" style_set=\"whatever\"/>"
#: ../src/ui/theme.c:5650 ../src/ui/theme.c:5712 ../src/ui/theme.c:5775
#, c-format
@ -1172,8 +1168,8 @@ msgid ""
"Cannot specify both \"button_width\"/\"button_height\" and \"aspect_ratio\" "
"for buttons"
msgstr ""
"No se puede especificar ambos «button_width»/«button_height» y «aspect "
"ratio» para los botones"
"No se puede especificar ambos «button_width»/«button_height» y «aspect ratio» "
"para los botones"
#: ../src/ui/theme-parser.c:1450
#, c-format
@ -1590,8 +1586,8 @@ msgid ""
"frame)\n"
msgstr ""
"Dibujó %d marcos en %g segundos del lado del cliente (%g milisegundos por "
"marco) y %g segundos de tiempo estándar incluyendo recursos del servidor X "
"(%g milisegundos por marco)\n"
"marco) y %g segundos de tiempo estándar incluyendo recursos del servidor X (%"
"g milisegundos por marco)\n"
#: ../src/ui/theme-viewer.c:1266
msgid "position expression test returned TRUE but set error"
@ -1956,13 +1952,13 @@ msgstr ""
#~ msgid "Error setting number of workspaces to %d: %s\n"
#~ msgstr ""
#~ "Ocurrió un error configurando la número de espacios de trabajo para %d: "
#~ "%s\n"
#~ "Ocurrió un error configurando la número de espacios de trabajo para %d: %"
#~ "s\n"
#~ msgid "Error setting name for workspace %d to \"%s\": %s\n"
#~ msgstr ""
#~ "Ocurrió un error al establecer el nombre del área de trabajo %d como "
#~ "«%s»: %s \n"
#~ "Ocurrió un error al establecer el nombre del área de trabajo %d como «%s»: "
#~ "%s \n"
#~ msgid "Error setting live hidden windows status status: %s\n"
#~ msgstr "Error al establecer el estado de vida de las ventanas ocultas: %s\n"
@ -1996,8 +1992,7 @@ msgstr ""
#~ msgid "Plugins to load for the Clutter-based compositing manager."
#~ msgstr ""
#~ "Complementos que cargar para la gestión de composición basada en "
#~ "«Clutter»."
#~ "Complementos que cargar para la gestión de composición basada en «Clutter»."
#~ msgid "Turn compositing on"
#~ msgstr "Activar la composición"
@ -2105,8 +2100,7 @@ msgstr ""
#~ "combinación de teclas para esta acción.\n"
#~ "\n"
#~ "Esta combinación de teclas puede invertirse manteniendo pulsada la tecla "
#~ "«Mayús»; por ello «Mayús» no puede ser una de las teclas de la "
#~ "combinación."
#~ "«Mayús»; por ello «Mayús» no puede ser una de las teclas de la combinación."
#~ msgid ""
#~ "Error launching metacity-dialog to warn about apps that don't support "
@ -2207,9 +2201,9 @@ msgstr ""
#~ "'beeps'; may be used in conjunction with 'visual bell' to allow silent "
#~ "'beeps'."
#~ msgstr ""
#~ "Determina si las aplicaciones o el sistema pueden generar «bips» "
#~ "audibles; podría usarse en conjunto con «la campana visual» para permitir "
#~ "«bips» silenciosos."
#~ "Determina si las aplicaciones o el sistema pueden generar «bips» audibles; "
#~ "podría usarse en conjunto con «la campana visual» para permitir «bips» "
#~ "silenciosos."
#~ msgid "Disable misfeatures that are required by old or broken applications"
#~ msgstr ""
@ -2233,13 +2227,13 @@ msgstr ""
#~ "working, and may also be a useful tradeoff for terminal servers. However, "
#~ "the wireframe feature is disabled when accessibility is on."
#~ msgstr ""
#~ "Si es «true», metacity dará al usuario menos información y menos "
#~ "sensación de «manipulación directa», usando marcos de alambre, evitando "
#~ "animaciones, u otros medios. Esto es una reducción significante en "
#~ "usabilidad para muchos usuarios, pero puede permitir funcionar a las "
#~ "aplicaciones heredadas y servidores de terminal cuando de otra forma "
#~ "sería impracticable. Sin embargo, la característica de marcos de alambre "
#~ "se desactiva cuando la accesibilidad está activada."
#~ "Si es «true», metacity dará al usuario menos información y menos sensación "
#~ "de «manipulación directa», usando marcos de alambre, evitando animaciones, "
#~ "u otros medios. Esto es una reducción significante en usabilidad para "
#~ "muchos usuarios, pero puede permitir funcionar a las aplicaciones "
#~ "heredadas y servidores de terminal cuando de otra forma sería "
#~ "impracticable. Sin embargo, la característica de marcos de alambre se "
#~ "desactiva cuando la accesibilidad está activada."
#~ msgid ""
#~ "If true, then Metacity works in terms of applications rather than "
@ -2287,8 +2281,8 @@ msgstr ""
#~ msgstr ""
#~ "Establezca esto a «verdadero» para redimensionar con el botón derecho y "
#~ "mostrar un menú con el botón del medio mientras se mantiene pulsada la "
#~ "tecla dada en \"mouse_button_modifier\"; establézcalo a «falso» para "
#~ "hacer que se comporte de forma contraria."
#~ "tecla dada en \"mouse_button_modifier\"; establézcalo a «falso» para hacer "
#~ "que se comporte de forma contraria."
#~ msgid ""
#~ "Setting this option to false can lead to buggy behavior, so users are "
@ -2310,8 +2304,8 @@ msgstr ""
#~ "for breaking their window manager and that they need to change this "
#~ "option back to true or live with the \"bug\" they requested."
#~ msgstr ""
#~ "Ajustar esta opción a «false» puede llevar a un comportamiento erróneo, "
#~ "de tal forma que se recomienda encarecidamente a los usuarios que no la "
#~ "Ajustar esta opción a «false» puede llevar a un comportamiento erróneo, de "
#~ "tal forma que se recomienda encarecidamente a los usuarios que no la "
#~ "cambien del valor «true». Muchas acciones (ej. pulsar en el área del "
#~ "cliente, mover o redimensionar la ventana) generalmente levantan la "
#~ "ventana como efecto colateral. Ajustar este valor a «false», algo que se "
@ -2460,8 +2454,8 @@ msgstr ""
#~ "Esta opción determina los efectos de la pulsación doble en la barra de "
#~ "títulos. Las opciones válidas actualmente son «toggle_shade», que enrolla/"
#~ "desenrolla la ventana, «toggle_maximized» que maximiza/desmaximiza la "
#~ "ventana, «toggle_maximize_horizontally» y «toggle_maximize_vertically» "
#~ "que maximiza/desmaximiza la ventana sólo en esa dirección, «minimize» que "
#~ "ventana, «toggle_maximize_horizontally» y «toggle_maximize_vertically» que "
#~ "maximiza/desmaximiza la ventana sólo en esa dirección, «minimize» que "
#~ "minimiza la ventana, «shade» que enrolla la ventana hacia arriba, «menu» "
#~ "que muestra la ventana de menú, «lower» que pone la ventana detrás de "
#~ "todas las demás y «none» que no hará nada."
@ -2521,8 +2515,8 @@ msgstr ""
#~ "environments."
#~ msgstr ""
#~ "Activa una indicación visual cuando una aplicación o el sistema emite una "
#~ "«campanada» o un «bip» ; es muy útil para los ambientes ruidosos y para "
#~ "las personas con dificultades auditivas."
#~ "«campanada» o un «bip» ; es muy útil para los ambientes ruidosos y para las "
#~ "personas con dificultades auditivas."
#~ msgid "Use standard system font in window titles"
#~ msgstr "Usar tipografía estándar del sistema en los títulos de la ventana"
@ -2601,11 +2595,11 @@ msgstr ""
#~ "will be no keybinding for this action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo por encima de la "
#~ "actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;"
#~ "F1». El intérprete es bastante liberal y permite tanto mayúsculas como "
#~ "minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;"
#~ "Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding that switches to the workspace below the current "
@ -2616,11 +2610,11 @@ msgstr ""
#~ "will be no keybinding for this action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo por debajo de la "
#~ "actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;"
#~ "F1». El intérprete es bastante liberal y permite tanto mayúsculas como "
#~ "minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;"
#~ "Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding that switches to the workspace on the left of the current "
@ -2631,12 +2625,11 @@ msgstr ""
#~ "will be no keybinding for this action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo hacia la izquierda "
#~ "de la actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;"
#~ "&lt;Alt&gt;F1». El intérprete es bastante liberal y permite tanto "
#~ "mayúsculas como minúsculas además de abreviaturas como por ejemplo «&lt;"
#~ "Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ "de la actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding that switches to the workspace on the right of the current "
@ -2647,12 +2640,11 @@ msgstr ""
#~ "will be no keybinding for this action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo hacia la derecha "
#~ "de la actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;"
#~ "&lt;Alt&gt;F1». El intérprete es bastante liberal y permite tanto "
#~ "mayúsculas como minúsculas además de abreviaturas como por ejemplo «&lt;"
#~ "Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ "de la actual. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding that switches to workspace 1. The format looks like \"&lt;"
@ -2663,10 +2655,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 1. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2678,10 +2670,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 10. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2693,10 +2685,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 11. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2708,10 +2700,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 12. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2723,10 +2715,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 2. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2738,10 +2730,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 3. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2755,8 +2747,8 @@ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 4. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2770,8 +2762,8 @@ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 5. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2785,8 +2777,8 @@ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 6. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2800,8 +2792,8 @@ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 7. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2815,8 +2807,8 @@ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 8. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2830,8 +2822,8 @@ msgstr ""
#~ "La combinación de teclas que cambia al área de trabajo 9. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2877,8 +2869,8 @@ msgstr ""
#~ "poder redimensionar una ventana utilizando el teclado. El formato se ve "
#~ "como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2906,10 +2898,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas usada para maximizar una ventana. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2921,10 +2913,10 @@ msgstr ""
#~ "action."
#~ msgstr ""
#~ "La combinación de teclas usada para minimizar una ventana. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -2939,8 +2931,8 @@ msgstr ""
#~ "hacia abajo. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window one workspace to the left. The "
@ -2967,12 +2959,11 @@ msgstr ""
#~ "keybinding for this action."
#~ msgstr ""
#~ "La combinación de teclas usada para mover una ventana un área de trabajo "
#~ "hacia la derecha. El formato se ve como «&lt;Control&gt;a» o «&lt;"
#~ "Mayús&gt;&lt;Alt&gt;F1». El intérprete es bastante liberal y permite "
#~ "tanto mayúsculas como minúsculas además de abreviaturas como por ejemplo "
#~ "«&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ "hacia la derecha. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;"
#~ "&lt;Alt&gt;F1». El intérprete es bastante liberal y permite tanto "
#~ "mayúsculas como minúsculas además de abreviaturas como por ejemplo «&lt;"
#~ "Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window one workspace up. The format looks "
@ -2983,12 +2974,11 @@ msgstr ""
#~ "this action."
#~ msgstr ""
#~ "La combinación de teclas usada para mover una ventana un área de trabajo "
#~ "hacia arriba. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;"
#~ "&lt;Alt&gt;F1». El intérprete es bastante liberal y permite tanto "
#~ "mayúsculas como minúsculas además de abreviaturas como por ejemplo «&lt;"
#~ "Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ "hacia arriba. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 1. The format looks "
@ -3002,8 +2992,8 @@ msgstr ""
#~ "trabajo 1. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 10. The format looks "
@ -3017,8 +3007,8 @@ msgstr ""
#~ "trabajo 10. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 11. The format looks "
@ -3032,8 +3022,8 @@ msgstr ""
#~ "trabajo 11. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 12. The format looks "
@ -3047,8 +3037,8 @@ msgstr ""
#~ "trabajo 12. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 2. The format looks "
@ -3062,8 +3052,8 @@ msgstr ""
#~ "trabajo 2. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 3. The format looks "
@ -3077,8 +3067,8 @@ msgstr ""
#~ "trabajo 3. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 4. The format looks "
@ -3092,8 +3082,8 @@ msgstr ""
#~ "trabajo 4. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 5. The format looks "
@ -3107,8 +3097,8 @@ msgstr ""
#~ "trabajo 5. El formato se ve como «&lt;Control&gt;a» o »&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 6. The format looks "
@ -3122,8 +3112,8 @@ msgstr ""
#~ "trabajo 6. El formato se ve como «&lt;Control&gt;a» o »&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 7. The format looks "
@ -3137,8 +3127,8 @@ msgstr ""
#~ "trabajo 7. El formato se ve como «&lt;Control&gt;a» o »&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 8. The format looks "
@ -3152,8 +3142,8 @@ msgstr ""
#~ "trabajo 8. El formato se ve como «&lt;Control&gt;a» o »&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move a window to workspace 9. The format looks "
@ -3167,8 +3157,8 @@ msgstr ""
#~ "trabajo 9. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move focus backwards between panels and the "
@ -3215,12 +3205,11 @@ msgstr ""
#~ "La combinación de teclas usada para retroceder el foco entre las ventanas "
#~ "de una aplicación sin una ventana emergente. Manteniendo pulsada la tecla "
#~ "«Mayús.» junto con esta combinación hace que la dirección vaya hacia "
#~ "adelante de nuevo. El formato se ve como «&lt;Control&gt;a» o «&lt;"
#~ "Mayús&gt;&lt;Alt&gt;F1». El analizador es bastante liberal y permite "
#~ "tanto mayúsculas como minúsculas además de abreviaturas como por ejemplo "
#~ "«&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ "adelante de nuevo. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;"
#~ "&lt;Alt&gt;F1». El analizador es bastante liberal y permite tanto "
#~ "mayúsculas como minúsculas además de abreviaturas como por ejemplo «&lt;"
#~ "Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move focus backwards between windows of an "
@ -3234,13 +3223,12 @@ msgstr ""
#~ msgstr ""
#~ "La combinación de teclas usada para retroceder el foco entre las ventanas "
#~ "de una aplicación, usando una ventana emergente. Manteniendo pulsada la "
#~ "tecla «Mayús.» junto con esta combinación hace que la dirección vaya "
#~ "hacia adelante de nuevo. El formato se ve como «&lt;Control&gt;a» o «&lt;"
#~ "Mayús&gt;&lt;Alt&gt;F1». El intérprete es bastante liberal y permite "
#~ "tanto mayúsculas como minúsculas además de abreviaturas como por ejemplo "
#~ "«&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ "tecla «Mayús.» junto con esta combinación hace que la dirección vaya hacia "
#~ "adelante de nuevo. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;"
#~ "&lt;Alt&gt;F1». El intérprete es bastante liberal y permite tanto "
#~ "mayúsculas como minúsculas además de abreviaturas como por ejemplo «&lt;"
#~ "Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move focus backwards between windows without a "
@ -3256,9 +3244,9 @@ msgstr ""
#~ "combinación hace que la dirección vaya hacia adelante de nuevo. El "
#~ "formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El "
#~ "analizador es bastante liberal y permite tanto mayúsculas como minúsculas "
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». "
#~ "Si configura esta opción con la cadena especial «disabled» entonces no "
#~ "habrá combinación de teclas para esta acción."
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move focus backwards between windows, using a "
@ -3326,8 +3314,8 @@ msgstr ""
#~ "movimiento. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El analizador es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move focus between windows of an application, "
@ -3344,8 +3332,8 @@ msgstr ""
#~ "Alt&gt;F6). El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to move focus between windows without a popup window. "
@ -3379,10 +3367,10 @@ msgstr ""
#~ msgstr ""
#~ "La combinación de teclas usada para mover el foco entre ventanas, usando "
#~ "una ventana emergente. (Tradicionalmente &lt;Alt&gt;Tab). El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -3395,10 +3383,10 @@ msgstr ""
#~ "keybinding for this action."
#~ msgstr ""
#~ "La combinación de teclas usada para activar siempre encima. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador es "
#~ "bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -3410,11 +3398,11 @@ msgstr ""
#~ "this action."
#~ msgstr ""
#~ "La combinación de teclas usada para activar el modo de pantalla completa. "
#~ "El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». "
#~ "El analizador es bastante liberal y permite tanto mayúsculas como "
#~ "minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;"
#~ "Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ "El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El "
#~ "analizador es bastante liberal y permite tanto mayúsculas como minúsculas "
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to toggle maximization. The format looks like \"&lt;"
@ -3427,8 +3415,8 @@ msgstr ""
#~ "La combinación de teclas usada para maximizar la ventana. El formato se "
#~ "ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
@ -3442,9 +3430,9 @@ msgstr ""
#~ "La combinación de teclas usada para enrollar o desenrollar la ventana. El "
#~ "formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El "
#~ "intérprete es bastante liberal y permite tanto mayúsculas como minúsculas "
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y »&lt;Ctrl&gt;». "
#~ "Si configura esta opción con la cadena especial «disabled» entonces no "
#~ "habrá combinación de teclas para esta acción."
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y »&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding used to toggle whether the window is on all workspaces or "
@ -3489,8 +3477,8 @@ msgstr ""
#~ "aplicación». El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding which invokes a terminal. The format looks like \"&lt;"
@ -3535,8 +3523,8 @@ msgstr ""
#~ "del panel. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "The keybinding which shows the panel's main menu. The format looks like "
@ -3570,8 +3558,8 @@ msgstr ""
#~ "ventanas. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El intérprete es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "»&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding lowers a window below other windows. The format looks "
@ -3582,11 +3570,11 @@ msgstr ""
#~ "this action."
#~ msgstr ""
#~ "Esta combinación de teclas coloca una ventana detrás de otras. El formato "
#~ "se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El "
#~ "analizador es bastante liberal y permite tanto mayúsculas como minúsculas "
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». "
#~ "Si configura esta opción con la cadena especial «disabled» entonces no "
#~ "habrá combinación de teclas para esta acción."
#~ "se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador "
#~ "es bastante liberal y permite tanto mayúsculas como minúsculas además de "
#~ "abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura "
#~ "esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding moves a window against the north (top) side of the "
@ -3600,23 +3588,23 @@ msgstr ""
#~ "pantalla. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El analizador es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding moves a window into the east (right) side of the screen. "
#~ "The format looks like \"&lt;Control&gt;a\" or \"&lt;Shift&gt;&lt;Alt&gt;"
#~ "F1\". The parser is fairly liberal and allows lower or upper case, and "
#~ "also abbreviations such as \"&lt;Ctl&gt;\" and \"&lt;Ctrl&gt;\". If you "
#~ "set the option to the special string \"disabled\", then there will be no "
#~ "The format looks like \"&lt;Control&gt;a\" or \"&lt;Shift&gt;&lt;Alt&gt;F1"
#~ "\". The parser is fairly liberal and allows lower or upper case, and also "
#~ "abbreviations such as \"&lt;Ctl&gt;\" and \"&lt;Ctrl&gt;\". If you set "
#~ "the option to the special string \"disabled\", then there will be no "
#~ "keybinding for this action."
#~ msgstr ""
#~ "Esta combinación de teclas coloca una ventana al este (derecha) de la "
#~ "pantalla. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El analizador es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding moves a window into the north-east (top right) corner of "
@ -3662,8 +3650,8 @@ msgstr ""
#~ "pantalla. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El analizador es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding moves a window into the south-east (bottom right) corner "
@ -3690,27 +3678,27 @@ msgstr ""
#~ "then there will be no keybinding for this action."
#~ msgstr ""
#~ "Esta combinación de teclas mueve una ventana a la esquina suroeste (abajo "
#~ "a la izquierda) de la pantalla. El formato se ve como «&lt;Control&gt;a» "
#~ "o «&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador es bastante liberal y "
#~ "permite tanto mayúsculas como minúsculas además de abreviaturas como por "
#~ "ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la "
#~ "cadena especial «disabled» entonces no habrá combinación de teclas para "
#~ "esta acción."
#~ "a la izquierda) de la pantalla. El formato se ve como «&lt;Control&gt;a» o "
#~ "«&lt;Mayús&gt;&lt;Alt&gt;F1». El analizador es bastante liberal y permite "
#~ "tanto mayúsculas como minúsculas además de abreviaturas como por ejemplo "
#~ "«&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ msgid ""
#~ "This keybinding moves a window into the west (left) side of the screen. "
#~ "The format looks like \"&lt;Control&gt;a\" or \"&lt;Shift&gt;&lt;Alt&gt;"
#~ "F1\". The parser is fairly liberal and allows lower or upper case, and "
#~ "also abbreviations such as \"&lt;Ctl&gt;\" and \"&lt;Ctrl&gt;\". If you "
#~ "set the option to the special string \"disabled\", then there will be no "
#~ "The format looks like \"&lt;Control&gt;a\" or \"&lt;Shift&gt;&lt;Alt&gt;F1"
#~ "\". The parser is fairly liberal and allows lower or upper case, and also "
#~ "abbreviations such as \"&lt;Ctl&gt;\" and \"&lt;Ctrl&gt;\". If you set "
#~ "the option to the special string \"disabled\", then there will be no "
#~ "keybinding for this action."
#~ msgstr ""
#~ "Esta combinación de teclas mueve una ventana al lado oeste (izquierdo) de "
#~ "la pantalla. El formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;"
#~ "Alt&gt;F1». El analizador es bastante liberal y permite tanto mayúsculas "
#~ "como minúsculas además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y "
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial "
#~ "«disabled» entonces no habrá combinación de teclas para esta acción."
#~ "«&lt;Ctrl&gt;». Si configura esta opción con la cadena especial «disabled» "
#~ "entonces no habrá combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding raises the window above other windows. The format looks "
@ -3723,9 +3711,9 @@ msgstr ""
#~ "Esta combinación de teclas eleva una ventana por encima de otras. El "
#~ "formato se ve como «&lt;Control&gt;a» o «&lt;Mayús&gt;&lt;Alt&gt;F1». El "
#~ "analizador es bastante liberal y permite tanto mayúsculas como minúsculas "
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». "
#~ "Si configura esta opción con la cadena especial «disabled» entonces no "
#~ "habrá combinación de teclas para esta acción."
#~ "además de abreviaturas como por ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si "
#~ "configura esta opción con la cadena especial «disabled» entonces no habrá "
#~ "combinación de teclas para esta acción."
#~ msgid ""
#~ "This keybinding resizes a window to fill available horizontal space. The "
@ -3736,8 +3724,8 @@ msgstr ""
#~ "keybinding for this action."
#~ msgstr ""
#~ "Esta combinación de teclas redimensiona una ventana para que rellene todo "
#~ "el espacio horizontal disponible. El formato se ve como «&lt;Control&gt;"
#~ "o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es bastante liberal y "
#~ "el espacio horizontal disponible. El formato se ve como «&lt;Control&gt;"
#~ "o «&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es bastante liberal y "
#~ "permite tanto mayúsculas como minúsculas además de abreviaturas como por "
#~ "ejemplo «&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la "
#~ "cadena especial «disabled» entonces no habrá combinación de teclas para "
@ -3752,12 +3740,12 @@ msgstr ""
#~ "keybinding for this action."
#~ msgstr ""
#~ "Esta combinación de teclas redimensiona una ventana para que rellene todo "
#~ "el espacio vertical disponible. El formato se ve como «&lt;Control&gt;a» "
#~ "o »&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es bastante liberal y "
#~ "permite tanto mayúsculas como minúsculas además de abreviaturas como por "
#~ "ejemplo »&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la "
#~ "cadena especial «disabled» entonces no habrá combinación de teclas para "
#~ "esta acción."
#~ "el espacio vertical disponible. El formato se ve como «&lt;Control&gt;a» o "
#~ "»&lt;Mayús&gt;&lt;Alt&gt;F1». El intérprete es bastante liberal y permite "
#~ "tanto mayúsculas como minúsculas además de abreviaturas como por ejemplo "
#~ "»&lt;Ctl&gt;» y «&lt;Ctrl&gt;». Si configura esta opción con la cadena "
#~ "especial «disabled» entonces no habrá combinación de teclas para esta "
#~ "acción."
#~ msgid "Toggle always on top state"
#~ msgstr "Cambiar el estado de siempre encima"

View File

@ -14,8 +14,8 @@ msgstr ""
"Project-Id-Version: mutter MASTER\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-09-22 18:05+0000\n"
"PO-Revision-Date: 2012-09-23 10:41+0300\n"
"POT-Creation-Date: 2012-10-17 20:44+0000\n"
"PO-Revision-Date: 2012-10-21 20:48+0300\n"
"Last-Translator: Mattias Põldaru <mahfiaz@gmail.com>\n"
"Language-Team: Estonian <>\n"
"Language: et\n"
@ -49,8 +49,8 @@ msgid "Unknown window information request: %d"
msgstr "Tundmatu aknateabe päring: %d"
#, c-format
msgid "%s is not responding."
msgstr "%s ei vasta."
msgid "%s is not responding."
msgstr "%s ei vasta."
msgid "Application is not responding."
msgstr "Rakendus ei vasta."
@ -396,6 +396,17 @@ msgstr ""
"Kui märgitud, siis on hüpikaken ja esiletõstmise raam keelatud akende "
"vahetamisel."
msgid "Delay focus changes until the pointer stops moving"
msgstr "Fookusemuutused lükatakse edasi kuni kursor peatub"
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Kui tõene ning fookusrežiim on kas \"sloppy\" või \"mouse\", siis fookust ei "
"vahetata kohe, kui kursor aknale liigub, vaid alles pärast kursori peatumist."
msgid "Draggable border width"
msgstr "Lohistatava äärise laius."

View File

@ -14,8 +14,8 @@ msgid ""
msgstr ""
"Project-Id-Version: gl\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-10-11 21:44+0200\n"
"PO-Revision-Date: 2012-10-11 22:02+0200\n"
"POT-Creation-Date: 2012-10-16 17:05+0200\n"
"PO-Revision-Date: 2012-10-16 17:06+0200\n"
"Last-Translator: Fran Dieguez <frandieguez@gnome.org>\n"
"Language-Team: gnome-l10n-gl@gnome.org\n"
"Language: gl\n"
@ -57,16 +57,16 @@ msgstr "Evento de campá"
msgid "Unknown window information request: %d"
msgstr "Petición de información de xanela descoñecida: %d"
#: ../src/core/delete.c:113
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "%s non está respondendo."
msgid "%s is not responding."
msgstr "«%s» non está respondendo."
#: ../src/core/delete.c:117
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "O Aplicativo non está respondendo."
#: ../src/core/delete.c:122
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -74,11 +74,11 @@ msgstr ""
"Pode elixir esperar un momento para ver se continúa ou forzar ao aplicativo "
"a pechar completamente."
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "Espe_rar"
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Forzar a saída"
@ -87,7 +87,7 @@ msgstr "_Forzar a saída"
msgid "Missing %s extension required for compositing"
msgstr "Falta a extensión %s que se require para a composición"
#: ../src/core/display.c:492
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Produciuse un erro ao abrir a visualización do X Window System «%s»\n"

View File

@ -11,8 +11,8 @@ msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-10-11 14:32+0000\n"
"PO-Revision-Date: 2012-10-11 21:44+0700\n"
"POT-Creation-Date: 2012-10-16 12:48+0000\n"
"PO-Revision-Date: 2012-10-16 23:40+0700\n"
"Last-Translator: Andika Triwidada <andika@gmail.com>\n"
"Language-Team: Indonesian <gnome@i15n.org>\n"
"Language: id\n"
@ -53,27 +53,27 @@ msgstr "Bel peristiwa"
msgid "Unknown window information request: %d"
msgstr "Permintaan informasi jendela tak dikenal: %d"
#: ../src/core/delete.c:113
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "%s tak merespon."
msgid "%s is not responding."
msgstr "\"%s\" tak merespon."
#: ../src/core/delete.c:117
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "Aplikasi tak merespon."
#: ../src/core/delete.c:122
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
msgstr ""
"Anda bisa memilih untuk menunggu sebentar atau memaksa aplikasi keluar."
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Tunggu"
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Matikan Paksa"
@ -82,7 +82,7 @@ msgstr "_Matikan Paksa"
msgid "Missing %s extension required for compositing"
msgstr "Kehilangan ekstensi %s yang diperlukan untuk pengkomposisian"
#: ../src/core/display.c:492
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Gagal membuka tampilan X Window System '%s'\n"

View File

@ -6,8 +6,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter 3.6.x\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-10-13 12:51+0200\n"
"PO-Revision-Date: 2012-10-13 12:51+0200\n"
"POT-Creation-Date: 2012-10-22 19:51+0200\n"
"PO-Revision-Date: 2012-10-22 19:52+0200\n"
"Last-Translator: Kjartan Maraas <kmaraas@gnome.org>\n"
"Language-Team: Norwegian bokmål <i18n-no@lister.ping.uio.no>\n"
"Language: \n"
@ -45,16 +45,16 @@ msgstr "Klokkehendelse"
msgid "Unknown window information request: %d"
msgstr "Ukjent forespørsel om vindusinformasjon: %d"
#: ../src/core/delete.c:113
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "%s svarer ikke."
msgid "%s is not responding."
msgstr "«%s» svarer ikke."
#: ../src/core/delete.c:117
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "Programmet svarer ikke."
#: ../src/core/delete.c:122
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -62,11 +62,11 @@ msgstr ""
"Du kan velge å vente en kort stund for å se om det fortsetter eller tvinge "
"programmet til å avslutte helt."
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Vent"
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Tvungen nedstenging"
@ -75,7 +75,7 @@ msgstr "_Tvungen nedstenging"
msgid "Missing %s extension required for compositing"
msgstr "Mangler utvidelsen %s som kreves for komposittfunksjon"
#: ../src/core/display.c:492
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Feil under åpning av X Window System skjerm «%s»\n"
@ -470,7 +470,7 @@ msgstr ""
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr ""
msgstr "Utsett fokusendringer til pekeren slutter å bevege seg"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""

View File

@ -10,16 +10,17 @@
# Rodrigo Flores <rodrigomarquesflores@gmail.com>, 2007.
# Djavan Fagundes <djavanf@gnome.org>, 2008, 2009, 2011.
# Vladimir Melo <vmelo@gnome.org>, 2009.
# Antonio Fernandes C. Neto <fernandes@pelivre.org>, 2010.
# Antonio Fernandes C. Neto <fernandesn@gnome.org>, 2010.
# Rodrigo Padula de Oliveira <contato@rodrigopadula.com>, 2011.
# Enrico Nicoletto <liverig@gmail.com>, 2012.
#
msgid ""
msgstr ""
"Project-Id-Version: metacity\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2012-09-17 16:25-0400\n"
"PO-Revision-Date: 2012-09-12 09:45-0300\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?"
"product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-10-26 13:53+0000\n"
"PO-Revision-Date: 2012-10-12 23:18-0300\n"
"Last-Translator: Rafael Ferreira <rafael.f.f1@gmail.com>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n"
@ -60,16 +61,16 @@ msgstr "Evento de som"
msgid "Unknown window information request: %d"
msgstr "Informação solicitada de janela desconhecida: %d"
#: ../src/core/delete.c:114
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "%s não está respondendo."
msgid "%s is not responding."
msgstr "\"%s\" não está respondendo."
#: ../src/core/delete.c:118
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "O aplicativo não está respondendo."
#: ../src/core/delete.c:123
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -77,20 +78,20 @@ msgstr ""
"Você pode escolher aguardar um pouco e continuar ou forçar o aplicativo a "
"sair completamente."
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Esperar"
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Forçar sair"
#: ../src/core/display.c:380
#: ../src/core/display.c:396
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Faltando extensão %s necessária para composição"
#: ../src/core/display.c:446
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Falha ao abrir a exibição \"%s\" do X Window System\n"
@ -165,7 +166,7 @@ msgstr "Versão impressa"
msgid "Mutter plugin to use"
msgstr "Plug-in do Mutter para usar"
#: ../src/core/prefs.c:1071
#: ../src/core/prefs.c:1079
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -173,14 +174,14 @@ msgstr ""
"As alternativas para aplicativos quebrados estão desabilitadas. É possível "
"que alguns aplicativos não funcionem de maneira adequada.\n"
#: ../src/core/prefs.c:1146
#: ../src/core/prefs.c:1154
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr ""
"Não foi possível analisar a descrição da fonte \"%s\" a partir da chave "
"GSettings %s\n"
#: ../src/core/prefs.c:1212
#: ../src/core/prefs.c:1220
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -189,7 +190,7 @@ msgstr ""
"\"%s\" localizado no banco de dados de configurações não é um valor válido "
"para o modificador de botão do mouse\n"
#: ../src/core/prefs.c:1736
#: ../src/core/prefs.c:1747
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
@ -198,7 +199,7 @@ msgstr ""
"\"%s\" localizado no banco de dados de configurações não é um valor válido "
"para a tecla de atalho \"%s\"\n"
#: ../src/core/prefs.c:1833
#: ../src/core/prefs.c:1844
#, c-format
msgid "Workspace %d"
msgstr "Espaço de trabalho %d"
@ -328,7 +329,7 @@ msgid "Window manager error: "
msgstr "Erro do gerenciador de janelas: "
#. first time through
#: ../src/core/window.c:7234
#: ../src/core/window.c:7240
#, c-format
msgid ""
"Window %s sets SM_CLIENT_ID on itself, instead of on the WM_CLIENT_LEADER "
@ -344,7 +345,7 @@ msgstr ""
#. * MWM but not WM_NORMAL_HINTS are basically broken. We complain
#. * about these apps but make them work.
#.
#: ../src/core/window.c:7899
#: ../src/core/window.c:7905
#, c-format
msgid ""
"Window %s sets an MWM hint indicating it isn't resizable, but sets min size "
@ -354,22 +355,22 @@ msgstr ""
"define o tamanho mínimo %d x %d e máximo %d x %d; isso não faz muito "
"sentido.\n"
#: ../src/core/window-props.c:310
#: ../src/core/window-props.c:274
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "O aplicativo definiu um _NET_WM_PID %lu inválido\n"
#: ../src/core/window-props.c:429
#: ../src/core/window-props.c:393
#, c-format
msgid "%s (on %s)"
msgstr "%s (em %s)"
#: ../src/core/window-props.c:1484
#: ../src/core/window-props.c:1448
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Janela WM_TRANSIENT_FOR inválida 0x%lx especificada para %s.\n"
#: ../src/core/window-props.c:1495
#: ../src/core/window-props.c:1459
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "Janela WM_TRANSIENT_FOR 0x%lx especificada para %s iriar criar loop.\n"
@ -493,10 +494,24 @@ msgstr ""
"desabilitados na alternância de janelas."
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr "Atrasar a alteração do foco até o ponteiro parar de mover"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Se verdadeiro, e o modo de foco for \"sloppy\" ou \"mouse\", o foco não será "
"alterado imediatamente ao entrar em uma janela, e sim somente após o "
"ponteiro parar de mover."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
msgstr "Largura da borda arrastável"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
msgid ""
"The amount of total draggable borders. If the theme's visible borders are "
"not enough, invisible borders will be added to meet this value."
@ -505,11 +520,11 @@ msgstr ""
"não são suficientes, as bordas invisíveis serão adicionadas para encontrar "
"este valor."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Select window from tab popup"
msgstr "Selecione a janela a partir da aba instantânea"
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
#: ../src/org.gnome.mutter.gschema.xml.in.h:18
msgid "Cancel tab popup"
msgstr "Cancelar aba instantânea"
@ -2172,18 +2187,6 @@ msgstr ""
#~ msgid "Enable Visual Bell"
#~ msgstr "Habilitar campainha visual"
#~ msgid ""
#~ "If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
#~ "the focused window will be automatically raised after a delay specified "
#~ "by the auto_raise_delay key. This is not related to clicking on a window "
#~ "to raise it, nor to entering a window during drag-and-drop."
#~ msgstr ""
#~ "Se verdadeiro, e o modo de foco for \"sloppy\" ou \"mouse\", a janela "
#~ "focada será automaticamente elevada após um atraso especificado pela "
#~ "chave auto_raise_delay. Isso não tem relação alguma com clicar em uma "
#~ "janela para elevá-la, ou alcançar uma janela durante uma ação de arrastar-"
#~ "e-soltar."
#~ msgid ""
#~ "If true, ignore the titlebar_font option, and use the standard "
#~ "application font for window titles."

View File

@ -10,8 +10,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-10-11 14:45+0000\n"
"PO-Revision-Date: 2012-10-11 19:56+0100\n"
"POT-Creation-Date: 2012-10-16 12:48+0000\n"
"PO-Revision-Date: 2012-10-16 14:57+0100\n"
"Last-Translator: Matej Urbančič <mateju@svn.gnome.org>\n"
"Language-Team: Slovenian GNOME Translation Team <gnome-si@googlegroups.com>\n"
"Language: \n"
@ -51,24 +51,24 @@ msgstr "Dogodek zvonjenja"
msgid "Unknown window information request: %d"
msgstr "Zahteva izpisa podrobnosti neznanega okna: %d"
#: ../src/core/delete.c:113
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
msgstr "Program %s se ne odziva."
msgid "%s is not responding."
msgstr "%s se ne odziva."
#: ../src/core/delete.c:117
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "Program se ne odziva."
#: ../src/core/delete.c:122
#: ../src/core/delete.c:118
msgid "You may choose to wait a short while for it to continue or force the application to quit entirely."
msgstr "Lahko še malo počakate, če program morda spet začne delovati, ali pa vsilite končanje delovanja."
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Počakaj"
#: ../src/core/delete.c:129
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Vsili konec"
@ -77,7 +77,7 @@ msgstr "_Vsili konec"
msgid "Missing %s extension required for compositing"
msgstr "Manjka razširitev %s, ki je ključna za sestavljanje"
#: ../src/core/display.c:492
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Ni mogoče odpreti zaslona '%s' okenskega sistema X\n"

View File

@ -10,16 +10,16 @@ msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter"
"&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-07-15 00:47+0000\n"
"PO-Revision-Date: 2012-07-22 09:20+0200\n"
"POT-Creation-Date: 2012-10-16 12:48+0000\n"
"PO-Revision-Date: 2012-10-16 20:28+0200\n"
"Last-Translator: Мирослав Николић <miroslavnikolic@rocketmail.com>\n"
"Language-Team: Serbian <gnom@prevod.org>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n"
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Project-Style: gnome\n"
#: ../src/50-mutter-windows.xml.in.h:1
@ -53,16 +53,17 @@ msgstr "Звонца"
msgid "Unknown window information request: %d"
msgstr "Захтевана је непозната информација о прозору: %d"
#: ../src/core/delete.c:114
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
#| msgid "%s is not responding."
msgid "“%s” is not responding."
msgstr "„%s“ не даје одзив."
#: ../src/core/delete.c:118
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "Програм не даје одзив."
#: ../src/core/delete.c:123
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -70,25 +71,25 @@ msgstr ""
"Можете мало сачекати док се програм не сабере или приморати програм да "
"комплетно прекине са радом."
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Сачекај"
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Приморај излаз"
#: ../src/core/display.c:380
#: ../src/core/display.c:396
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Недостаје потребан композитни додатак %s"
#: ../src/core/display.c:446
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Нисам успео да отворим екран „%s“ Икс система прозора\n"
#: ../src/core/keybindings.c:844
#: ../src/core/keybindings.c:853
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -157,7 +158,7 @@ msgstr "Исписује издање"
msgid "Mutter plugin to use"
msgstr "Прикључци Матера за коришћење"
#: ../src/core/prefs.c:1065
#: ../src/core/prefs.c:1079
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -165,12 +166,12 @@ msgstr ""
"Решења за оштећене програме су искључена. Неке апликације се могу понашати "
"чудно.\n"
#: ../src/core/prefs.c:1140
#: ../src/core/prefs.c:1154
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Не могу да обрадим опис „%s“ из кључа „%s“ у Гномовим подешавањима\n"
#: ../src/core/prefs.c:1206
#: ../src/core/prefs.c:1220
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -179,14 +180,14 @@ msgstr ""
"„%s“ је пронађен у бази подешавања што није исправна вредност која мења "
"понашање тастера миша\n"
#: ../src/core/prefs.c:1724
#: ../src/core/prefs.c:1747
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
"\"%s\"\n"
msgstr "„%s“ из базе са подешавањима није исправна комбинација тастера „%s“\n"
#: ../src/core/prefs.c:1821
#: ../src/core/prefs.c:1844
#, c-format
msgid "Workspace %d"
msgstr "%d. радни простор"
@ -336,25 +337,25 @@ msgid ""
"%d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr ""
"Прозор „%s“ је поставио „MWM“ што наговештава да није променљиве величине, "
"али је поставио најмању величину %d x %d и највећу величину %d x %d што "
"нема много смисла.\n"
"али је поставио најмању величину %d x %d и највећу величину %d x %d што нема "
"много смисла.\n"
#: ../src/core/window-props.c:310
#: ../src/core/window-props.c:274
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Програм је поставио нетачан _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:429
#: ../src/core/window-props.c:393
#, c-format
msgid "%s (on %s)"
msgstr "%s (на %s)"
#: ../src/core/window-props.c:1484
#: ../src/core/window-props.c:1448
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Неисправан прозор 0x%lx наведен као WM_TRANSIENT_FOR за %s.\n"
#: ../src/core/window-props.c:1495
#: ../src/core/window-props.c:1459
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR прозор 0x%lx за %s ће направити петљу.\n"
@ -474,10 +475,24 @@ msgstr ""
"кретање по прозорима."
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr "Застој првог плана се мења док се показивач не заустави"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Ако је изабрано, а режим првог плана је или „sloppy“ или „mouse“ онда први "
"план неће бити мењан одмах по уласку у прозор, већ само након што показивач "
"престане да се помера."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
msgstr "Ширина ивице за превлачење"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
msgid ""
"The amount of total draggable borders. If the theme's visible borders are "
"not enough, invisible borders will be added to meet this value."
@ -485,11 +500,11 @@ msgstr ""
"Износ укупне ивице за превлачење. Ако видљиве ивице теме нису довољне, биће "
"додате невидљиве ивице за достизање ове вредности."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Select window from tab popup"
msgstr "Бира прозор из језичка искакања"
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
#: ../src/org.gnome.mutter.gschema.xml.in.h:18
msgid "Cancel tab popup"
msgstr "Отказивање језичка искакања"
@ -937,8 +952,8 @@ msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
"specified for this frame style"
msgstr ""
"<button function=„%s“ state=„%s“ draw_ops=\"whatever\"/> мора бити наведен за "
"овај стил оквира"
"<button function=„%s“ state=„%s“ draw_ops=\"whatever\"/> мора бити наведен "
"за овај стил оквира"
#: ../src/ui/theme.c:5009 ../src/ui/theme.c:5034
#, c-format

View File

@ -10,16 +10,16 @@ msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: http://bugzilla.gnome.org/enter_bug.cgi?product=mutter"
"&keywords=I18N+L10N&component=general\n"
"POT-Creation-Date: 2012-07-15 00:47+0000\n"
"PO-Revision-Date: 2012-07-22 09:20+0200\n"
"POT-Creation-Date: 2012-10-16 12:48+0000\n"
"PO-Revision-Date: 2012-10-16 20:28+0200\n"
"Last-Translator: Miroslav Nikolić <miroslavnikolic@rocketmail.com>\n"
"Language-Team: Serbian <gnom@prevod.org>\n"
"Language: sr\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : n"
"%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"Plural-Forms: nplurals=4; plural=n==1? 3 : n%10==1 && n%100!=11 ? 0 : "
"n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
"X-Project-Style: gnome\n"
#: ../src/50-mutter-windows.xml.in.h:1
@ -53,16 +53,17 @@ msgstr "Zvonca"
msgid "Unknown window information request: %d"
msgstr "Zahtevana je nepoznata informacija o prozoru: %d"
#: ../src/core/delete.c:114
#: ../src/core/delete.c:111
#, c-format
msgid "%s is not responding."
#| msgid "%s is not responding."
msgid "“%s” is not responding."
msgstr "„%s“ ne daje odziv."
#: ../src/core/delete.c:118
#: ../src/core/delete.c:113
msgid "Application is not responding."
msgstr "Program ne daje odziv."
#: ../src/core/delete.c:123
#: ../src/core/delete.c:118
msgid ""
"You may choose to wait a short while for it to continue or force the "
"application to quit entirely."
@ -70,25 +71,25 @@ msgstr ""
"Možete malo sačekati dok se program ne sabere ili primorati program da "
"kompletno prekine sa radom."
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Wait"
msgstr "_Sačekaj"
#: ../src/core/delete.c:130
#: ../src/core/delete.c:125
msgid "_Force Quit"
msgstr "_Primoraj izlaz"
#: ../src/core/display.c:380
#: ../src/core/display.c:396
#, c-format
msgid "Missing %s extension required for compositing"
msgstr "Nedostaje potreban kompozitni dodatak %s"
#: ../src/core/display.c:446
#: ../src/core/display.c:493
#, c-format
msgid "Failed to open X Window System display '%s'\n"
msgstr "Nisam uspeo da otvorim ekran „%s“ Iks sistema prozora\n"
#: ../src/core/keybindings.c:844
#: ../src/core/keybindings.c:853
#, c-format
msgid ""
"Some other program is already using the key %s with modifiers %x as a "
@ -157,7 +158,7 @@ msgstr "Ispisuje izdanje"
msgid "Mutter plugin to use"
msgstr "Priključci Matera za korišćenje"
#: ../src/core/prefs.c:1065
#: ../src/core/prefs.c:1079
msgid ""
"Workarounds for broken applications disabled. Some applications may not "
"behave properly.\n"
@ -165,12 +166,12 @@ msgstr ""
"Rešenja za oštećene programe su isključena. Neke aplikacije se mogu ponašati "
"čudno.\n"
#: ../src/core/prefs.c:1140
#: ../src/core/prefs.c:1154
#, c-format
msgid "Could not parse font description \"%s\" from GSettings key %s\n"
msgstr "Ne mogu da obradim opis „%s“ iz ključa „%s“ u Gnomovim podešavanjima\n"
#: ../src/core/prefs.c:1206
#: ../src/core/prefs.c:1220
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for mouse button "
@ -179,14 +180,14 @@ msgstr ""
"„%s“ je pronađen u bazi podešavanja što nije ispravna vrednost koja menja "
"ponašanje tastera miša\n"
#: ../src/core/prefs.c:1724
#: ../src/core/prefs.c:1747
#, c-format
msgid ""
"\"%s\" found in configuration database is not a valid value for keybinding "
"\"%s\"\n"
msgstr "„%s“ iz baze sa podešavanjima nije ispravna kombinacija tastera „%s“\n"
#: ../src/core/prefs.c:1821
#: ../src/core/prefs.c:1844
#, c-format
msgid "Workspace %d"
msgstr "%d. radni prostor"
@ -336,25 +337,25 @@ msgid ""
"%d x %d and max size %d x %d; this doesn't make much sense.\n"
msgstr ""
"Prozor „%s“ je postavio „MWM“ što nagoveštava da nije promenljive veličine, "
"ali je postavio najmanju veličinu %d x %d i najveću veličinu %d x %d što "
"nema mnogo smisla.\n"
"ali je postavio najmanju veličinu %d x %d i najveću veličinu %d x %d što nema "
"mnogo smisla.\n"
#: ../src/core/window-props.c:310
#: ../src/core/window-props.c:274
#, c-format
msgid "Application set a bogus _NET_WM_PID %lu\n"
msgstr "Program je postavio netačan _NET_WM_PID %lu\n"
#: ../src/core/window-props.c:429
#: ../src/core/window-props.c:393
#, c-format
msgid "%s (on %s)"
msgstr "%s (na %s)"
#: ../src/core/window-props.c:1484
#: ../src/core/window-props.c:1448
#, c-format
msgid "Invalid WM_TRANSIENT_FOR window 0x%lx specified for %s.\n"
msgstr "Neispravan prozor 0x%lx naveden kao WM_TRANSIENT_FOR za %s.\n"
#: ../src/core/window-props.c:1495
#: ../src/core/window-props.c:1459
#, c-format
msgid "WM_TRANSIENT_FOR window 0x%lx for %s would create loop.\n"
msgstr "WM_TRANSIENT_FOR prozor 0x%lx za %s će napraviti petlju.\n"
@ -474,10 +475,24 @@ msgstr ""
"kretanje po prozorima."
#: ../src/org.gnome.mutter.gschema.xml.in.h:13
msgid "Delay focus changes until the pointer stops moving"
msgstr "Zastoj prvog plana se menja dok se pokazivač ne zaustavi"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
msgid ""
"If set to true, and the focus mode is either \"sloppy\" or \"mouse\" then "
"the focus will not be changed immediately when entering a window, but only "
"after the pointer stops moving."
msgstr ""
"Ako je izabrano, a režim prvog plana je ili „sloppy“ ili „mouse“ onda prvi "
"plan neće biti menjan odmah po ulasku u prozor, već samo nakon što pokazivač "
"prestane da se pomera."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
msgid "Draggable border width"
msgstr "Širina ivice za prevlačenje"
#: ../src/org.gnome.mutter.gschema.xml.in.h:14
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
msgid ""
"The amount of total draggable borders. If the theme's visible borders are "
"not enough, invisible borders will be added to meet this value."
@ -485,11 +500,11 @@ msgstr ""
"Iznos ukupne ivice za prevlačenje. Ako vidljive ivice teme nisu dovoljne, biće "
"dodate nevidljive ivice za dostizanje ove vrednosti."
#: ../src/org.gnome.mutter.gschema.xml.in.h:15
#: ../src/org.gnome.mutter.gschema.xml.in.h:17
msgid "Select window from tab popup"
msgstr "Bira prozor iz jezička iskakanja"
#: ../src/org.gnome.mutter.gschema.xml.in.h:16
#: ../src/org.gnome.mutter.gschema.xml.in.h:18
msgid "Cancel tab popup"
msgstr "Otkazivanje jezička iskakanja"
@ -937,8 +952,8 @@ msgid ""
"<button function=\"%s\" state=\"%s\" draw_ops=\"whatever\"/> must be "
"specified for this frame style"
msgstr ""
"<button function=„%s“ state=„%s“ draw_ops=\"whatever\"/> mora biti naveden za "
"ovaj stil okvira"
"<button function=„%s“ state=„%s“ draw_ops=\"whatever\"/> mora biti naveden "
"za ovaj stil okvira"
#: ../src/ui/theme.c:5009 ../src/ui/theme.c:5034
#, c-format

View File

@ -75,6 +75,20 @@ libmutter_la_SOURCES = \
core/constraints.h \
core/core.c \
core/delete.c \
core/device.c \
meta/device.h \
core/device-keyboard.c \
core/device-keyboard.h \
core/device-pointer.c \
core/device-pointer.h \
core/device-private.h \
core/device-map.c \
meta/device-map.h \
core/device-map-private.h \
core/device-map-core.c \
core/device-map-core.h \
core/devices-core.c \
core/devices-core.h \
core/display.c \
core/display-private.h \
meta/display.h \
@ -97,6 +111,8 @@ libmutter_la_SOURCES = \
meta/group.h \
core/iconcache.c \
core/iconcache.h \
core/input-events.c \
core/input-events.h \
core/keybindings.c \
core/keybindings-private.h \
core/main.c \
@ -151,6 +167,14 @@ libmutter_la_SOURCES = \
ui/preview-widget.c \
$(mutter_built_sources)
if HAVE_XINPUT2
libmutter_la_SOURCES += \
core/device-map-xi2.c \
core/device-map-xi2.h \
core/devices-xi2.c \
core/devices-xi2.h
endif
libmutter_la_LDFLAGS = -no-undefined
libmutter_la_LIBADD = $(MUTTER_LIBS)
@ -161,6 +185,8 @@ libmutterinclude_base_headers = \
meta/common.h \
meta/compositor-mutter.h \
meta/compositor.h \
meta/device.h \
meta/device-map.h \
meta/display.h \
meta/errors.h \
meta/gradient.h \

View File

@ -18,6 +18,8 @@
#include "meta-background-actor-private.h"
#include "window-private.h" /* to check window->hidden */
#include "display-private.h" /* for meta_display_lookup_x_window() */
#include "core.h" /* for meta_core_select_events() */
#include "input-events.h"
#include <X11/extensions/shape.h>
#include <X11/extensions/Xcomposite.h>
@ -155,7 +157,6 @@ get_output_window (MetaScreen *screen)
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdisplay = meta_display_get_xdisplay (display);
Window output, xroot;
XWindowAttributes attr;
long event_mask;
xroot = meta_screen_get_xroot (screen);
@ -169,13 +170,7 @@ get_output_window (MetaScreen *screen)
KeyPressMask | KeyReleaseMask;
output = XCompositeGetOverlayWindow (xdisplay, xroot);
if (XGetWindowAttributes (xdisplay, output, &attr))
{
event_mask |= attr.your_event_mask;
}
XSelectInput (xdisplay, output, event_mask);
meta_core_select_events (xdisplay, output, event_mask, TRUE);
return output;
}
@ -347,26 +342,34 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
* merge the two.
*/
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
gboolean pointer_grabbed = FALSE;
gboolean keyboard_grabbed = FALSE;
int result;
gboolean result;
MetaDevice *device;
MetaGrabInfo *grab_info;
if (compositor->modal_plugin != NULL || display->grab_op != META_GRAB_OP_NONE)
/* FIXME: need a real device here, and probably
* some exclusion mode for other devices */
device = meta_device_map_lookup (display->device_map,
META_CORE_POINTER_ID);
grab_info = meta_display_get_grab_info (display, device);
if (compositor->modal_plugin != NULL || grab_info != NULL)
return FALSE;
if ((options & META_MODAL_POINTER_ALREADY_GRABBED) == 0)
{
result = XGrabPointer (xdpy, grab_window,
False, /* owner_events */
(ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask | PointerMotionMask),
GrabModeAsync, GrabModeAsync,
None, /* confine to */
cursor,
timestamp);
if (result != Success)
result = meta_device_grab (device,
grab_window,
(ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask | PointerMotionMask),
cursor,
FALSE,
FALSE,
timestamp);
if (!result)
goto fail;
pointer_grabbed = TRUE;
@ -374,22 +377,25 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
if ((options & META_MODAL_KEYBOARD_ALREADY_GRABBED) == 0)
{
result = XGrabKeyboard (xdpy, grab_window,
False, /* owner_events */
GrabModeAsync, GrabModeAsync,
timestamp);
if (result != Success)
result = meta_device_grab (meta_device_get_paired_device (device),
grab_window,
(KeyPressMask | KeyReleaseMask),
META_CURSOR_DEFAULT,
FALSE, FALSE,
timestamp);
if (!result)
goto fail;
keyboard_grabbed = TRUE;
}
display->grab_op = META_GRAB_OP_COMPOSITOR;
display->grab_window = NULL;
display->grab_screen = screen;
display->grab_have_pointer = TRUE;
display->grab_have_keyboard = TRUE;
grab_info = meta_display_create_grab_info (display, device);
grab_info->grab_op = META_GRAB_OP_COMPOSITOR;
grab_info->grab_window = NULL;
grab_info->grab_screen = screen;
grab_info->grab_have_pointer = TRUE;
grab_info->grab_have_keyboard = TRUE;
compositor->modal_plugin = plugin;
@ -397,9 +403,9 @@ meta_begin_modal_for_plugin (MetaScreen *screen,
fail:
if (pointer_grabbed)
XUngrabPointer (xdpy, timestamp);
meta_device_ungrab (device, timestamp);
if (keyboard_grabbed)
XUngrabKeyboard (xdpy, timestamp);
meta_device_ungrab (meta_device_get_paired_device (device), timestamp);
return FALSE;
}
@ -410,20 +416,19 @@ meta_end_modal_for_plugin (MetaScreen *screen,
guint32 timestamp)
{
MetaDisplay *display = meta_screen_get_display (screen);
Display *xdpy = meta_display_get_xdisplay (display);
MetaCompositor *compositor = display->compositor;
MetaDevice *device;
g_return_if_fail (compositor->modal_plugin == plugin);
XUngrabPointer (xdpy, timestamp);
XUngrabKeyboard (xdpy, timestamp);
/* FIXME: need a real device here */
device = meta_device_map_lookup (display->device_map,
META_CORE_POINTER_ID);
display->grab_op = META_GRAB_OP_NONE;
display->grab_window = NULL;
display->grab_screen = NULL;
display->grab_have_pointer = FALSE;
display->grab_have_keyboard = FALSE;
meta_device_ungrab (device, timestamp);
meta_device_ungrab (meta_device_get_paired_device (device), timestamp);
meta_display_remove_grab_info (display, device);
compositor->modal_plugin = NULL;
}
@ -456,7 +461,6 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
Window xroot = meta_screen_get_xroot (screen);
Window xwin;
gint width, height;
XWindowAttributes attr;
long event_mask;
guint n_retries;
guint max_retries;
@ -533,12 +537,7 @@ meta_compositor_manage_screen (MetaCompositor *compositor,
KeyPressMask | KeyReleaseMask |
StructureNotifyMask;
if (XGetWindowAttributes (xdisplay, xwin, &attr))
{
event_mask |= attr.your_event_mask;
}
XSelectInput (xdisplay, xwin, event_mask);
meta_core_select_events (xdisplay, xwin, event_mask, TRUE);
info->window_group = meta_window_group_new (screen);
info->background_actor = meta_background_actor_new_for_screen (screen);
@ -695,9 +694,15 @@ meta_compositor_set_updates (MetaCompositor *compositor,
}
static gboolean
is_grabbed_event (XEvent *event)
is_grabbed_event (MetaDisplay *display,
XEvent *event)
{
switch (event->xany.type)
guint evtype;
if (!meta_input_event_get_type (display, event, &evtype))
return FALSE;
switch (evtype)
{
case ButtonPress:
case ButtonRelease:
@ -730,7 +735,8 @@ meta_compositor_process_event (MetaCompositor *compositor,
XEvent *event,
MetaWindow *window)
{
if (compositor->modal_plugin && is_grabbed_event (event))
if (compositor->modal_plugin &&
is_grabbed_event (compositor->display, event))
{
MetaPluginClass *klass = META_PLUGIN_GET_CLASS (compositor->modal_plugin);

View File

@ -305,8 +305,8 @@ meta_plugin_manager_xevent_filter (MetaPluginManager *plugin_mgr,
* of that plugin to pass events to Clutter. Otherwise, we send the
* event directly to Clutter ourselves.
*/
if (klass->xevent_filter && klass->xevent_filter (plugin, xev))
return TRUE;
if (klass->xevent_filter)
return klass->xevent_filter (plugin, xev);
else
return clutter_x11_handle_event (xev) != CLUTTER_X11_FILTER_CONTINUE;
}

View File

@ -239,6 +239,35 @@ bell_flash_window_frame (MetaWindow *window)
bell_unflash_frame, window->frame, NULL);
}
static MetaWindow *
get_flash_window (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
{
XkbBellNotifyEvent *xkb_bell_event;
MetaWindow *window;
g_assert (xkb_ev->xkb_type == XkbBellNotify);
xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
if (!window &&
g_hash_table_size (display->focus_info) == 1)
{
GHashTableIter iter;
MetaFocusInfo *info;
/* If there is only one focused window, use it */
g_hash_table_iter_init (&iter, display->focus_info);
if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &info) &&
info->focus_window && info->focus_window->frame)
window = info->focus_window;
}
return window;
}
/**
* bell_flash_frame:
* @display: The display the bell event came in on
@ -251,15 +280,11 @@ static void
bell_flash_frame (MetaDisplay *display,
XkbAnyEvent *xkb_ev)
{
XkbBellNotifyEvent *xkb_bell_event = (XkbBellNotifyEvent *) xkb_ev;
MetaWindow *window;
g_assert (xkb_ev->xkb_type == XkbBellNotify);
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
if (!window && (display->focus_window))
{
window = display->focus_window;
}
window = get_flash_window (display, xkb_ev);
if (window && window->frame)
{
bell_flash_window_frame (window);
@ -320,9 +345,7 @@ meta_bell_notify (MetaDisplay *display,
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
window = meta_display_lookup_x_window (display, xkb_bell_event->window);
if (!window && (display->focus_window) && (display->focus_window->frame))
window = display->focus_window;
window = get_flash_window (display, xkb_ev);
if (window)
{

View File

@ -1365,15 +1365,18 @@ constrain_titlebar_visible (MetaWindow *window,
int bottom_amount;
int horiz_amount_offscreen, vert_amount_offscreen;
int horiz_amount_onscreen, vert_amount_onscreen;
MetaGrabInfo *grab_info;
if (priority > PRIORITY_TITLEBAR_VISIBLE)
return TRUE;
grab_info = window->cur_grab;
/* Allow the titlebar beyond the top of the screen only if the user wasn't
* clicking on the frame to start the move.
*/
unconstrained_user_action =
info->is_user_action && !window->display->grab_frame_action;
info->is_user_action && (!grab_info || !grab_info->grab_frame_action);
/* Exit early if we know the constraint won't apply--note that this constraint
* is only meant for normal windows (e.g. we don't want docks to be shoved

View File

@ -30,6 +30,11 @@
#include <meta/prefs.h>
#include <meta/errors.h>
#ifdef HAVE_XINPUT2
#include <X11/extensions/XInput2.h>
#include "devices-xi2.h"
#endif
/* Looks up the MetaWindow representing the frame of the given X window.
* Used as a helper function by a bunch of the functions below.
*
@ -245,9 +250,19 @@ lower_window_and_transients (MetaWindow *window,
void
meta_core_user_lower_and_unfocus (Display *xdisplay,
Window frame_xwindow,
int device_id,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
MetaDevice *pointer;
pointer = meta_device_map_lookup (window->display->device_map, device_id);
if (pointer == NULL)
return;
if (!META_IS_DEVICE_POINTER (pointer))
pointer = meta_device_get_paired_device (pointer);
lower_window_and_transients (window, NULL);
@ -256,6 +271,7 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
* this will be invoked via keyboard action or by a mouse action;
* in either case the window or a modal child will have been focused.) */
meta_workspace_focus_default_window (window->screen->active_workspace,
pointer,
NULL,
timestamp);
}
@ -263,16 +279,21 @@ meta_core_user_lower_and_unfocus (Display *xdisplay,
void
meta_core_lower_beneath_grab_window (Display *xdisplay,
Window xwindow,
int device_id,
guint32 timestamp)
{
XWindowChanges changes;
MetaDisplay *display;
MetaScreen *screen;
MetaWindow *grab_window;
MetaDevice *pointer;
MetaGrabInfo *grab_info;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, xwindow);
grab_window = display->grab_window;
pointer = meta_device_map_lookup (display->device_map, device_id);
grab_info = meta_display_get_grab_info (display, pointer);
grab_window = grab_info->grab_window;
if (grab_window == NULL)
return;
@ -491,18 +512,27 @@ meta_core_get_active_workspace (Screen *xscreen)
void
meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,
int device_id,
int root_x,
int root_y,
int button,
guint32 timestamp)
{
MetaWindow *window = get_window (xdisplay, frame_xwindow);
MetaDevice *device;
/* There is already a menu popped up,
* most likely from another device
*/
if (window->menu)
return;
if (meta_prefs_get_raise_on_click ())
meta_window_raise (window);
meta_window_focus (window, timestamp);
meta_window_show_menu (window, root_x, root_y, button, timestamp);
device = meta_device_map_lookup (window->display->device_map, device_id);
meta_window_show_menu (window, device, root_x, root_y, button, timestamp);
}
void
@ -638,6 +668,7 @@ meta_core_get_workspace_name_with_index (Display *xdisplay,
gboolean
meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,
int device_id,
MetaGrabOp op,
gboolean pointer_already_grabbed,
gboolean frame_action,
@ -650,13 +681,16 @@ meta_core_begin_grab_op (Display *xdisplay,
MetaWindow *window = get_window (xdisplay, frame_xwindow);
MetaDisplay *display;
MetaScreen *screen;
MetaDevice *device;
display = meta_display_for_x_display (xdisplay);
screen = meta_display_screen_for_xwindow (display, frame_xwindow);
g_assert (screen != NULL);
return meta_display_begin_grab_op (display, screen, window,
device = meta_device_map_lookup (display->device_map, device_id);
return meta_display_begin_grab_op (display, screen, window, device,
op, pointer_already_grabbed,
frame_action,
button, modmask,
@ -665,57 +699,58 @@ meta_core_begin_grab_op (Display *xdisplay,
void
meta_core_end_grab_op (Display *xdisplay,
int device_id,
guint32 timestamp)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
MetaDevice *device;
meta_display_end_grab_op (display, timestamp);
display = meta_display_for_x_display (xdisplay);
device = meta_device_map_lookup (display->device_map, device_id);
meta_display_end_grab_op (display, device, timestamp);
}
MetaGrabOp
meta_core_get_grab_op (Display *xdisplay)
meta_core_frame_has_grab (Display *xdisplay,
Window frame_xwindow,
gint *device_id,
gint *button_ret)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
MetaWindow *window;
return display->grab_op;
window = get_window (xdisplay, frame_xwindow);
if (window != NULL &&
window->cur_grab != NULL)
{
if (button_ret)
*button_ret = window->cur_grab->grab_button;
if (device_id)
*device_id = meta_device_get_id (window->cur_grab->grab_pointer);
return window->cur_grab->grab_op;
}
return META_GRAB_OP_NONE;
}
Window
meta_core_get_grab_frame (Display *xdisplay)
meta_core_get_frame (Display *xdisplay,
Window client_xwindow)
{
MetaDisplay *display;
MetaWindow *window;
display = meta_display_for_x_display (xdisplay);
window = meta_display_lookup_x_window (display, client_xwindow);
g_assert (display != NULL);
g_assert (display->grab_op == META_GRAB_OP_NONE ||
display->grab_screen != NULL);
g_assert (display->grab_op == META_GRAB_OP_NONE ||
display->grab_screen->display->xdisplay == xdisplay);
if (display->grab_op != META_GRAB_OP_NONE &&
display->grab_window &&
display->grab_window->frame)
return display->grab_window->frame->xwindow;
else
return None;
}
if (window &&
window->frame)
return window->frame->xwindow;
int
meta_core_get_grab_button (Display *xdisplay)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
if (display->grab_op == META_GRAB_OP_NONE)
return -1;
return display->grab_button;
return None;
}
void
@ -731,13 +766,24 @@ meta_core_grab_buttons (Display *xdisplay,
}
void
meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
MetaCursor cursor)
meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
gint device_id,
MetaCursor cursor)
{
MetaWindow *window = get_window (xdisplay, frame_on_screen);
MetaDevice *pointer;
meta_frame_set_screen_cursor (window->frame, cursor);
pointer = meta_device_map_lookup (window->display->device_map,
device_id);
if (pointer == NULL)
return;
if (!META_IS_DEVICE_POINTER (pointer))
pointer = meta_device_get_paired_device (pointer);
meta_frame_set_screen_cursor (window->frame, pointer, cursor);
}
void
@ -775,3 +821,69 @@ meta_invalidate_default_icons (void)
g_slist_free (windows);
}
/* Selects events on an xwindow, using XInput2 if available/in use,
* this function doesn't require the xwindow to have a backing
* MetaWindow.
*/
void
meta_core_select_events (Display *xdisplay,
Window xwindow,
gint evmask,
gboolean preserve_old_mask)
{
MetaDisplay *display;
display = meta_display_for_x_display (xdisplay);
#ifdef HAVE_XINPUT2
if (display->have_xinput2)
{
XIEventMask mask;
mask.deviceid = XIAllMasterDevices;
mask.mask = meta_device_xi2_translate_event_mask (evmask,
&mask.mask_len);
if (preserve_old_mask)
{
XIEventMask *prev;
gint n_masks, i, j;
prev = XIGetSelectedEvents (xdisplay, xwindow, &n_masks);
for (i = 0; i < n_masks; i++)
{
if (prev[i].deviceid != XIAllMasterDevices)
continue;
for (j = 0; j < MIN (mask.mask_len, prev[i].mask_len); j++)
mask.mask[j] |= prev[i].mask[j];
}
XFree (prev);
}
XISelectEvents (xdisplay, xwindow, &mask, 1);
/* Unset any input event so they are only handled via XInput2 */
evmask &= ~(KeyPressMask | KeyReleaseMask |
ButtonPressMask | ButtonReleaseMask |
EnterWindowMask | LeaveWindowMask |
PointerMotionMask | PointerMotionHintMask |
Button1MotionMask | Button2MotionMask |
Button3MotionMask | Button4MotionMask |
Button5MotionMask | ButtonMotionMask |
FocusChangeMask);
}
#endif
if (preserve_old_mask)
{
XWindowAttributes attr;
if (XGetWindowAttributes (xdisplay, xwindow, &attr))
evmask |= attr.your_event_mask;
}
XSelectInput (xdisplay, xwindow, evmask);
}

View File

@ -110,6 +110,7 @@ void meta_core_user_raise (Display *xdisplay,
Window frame_xwindow);
void meta_core_user_lower_and_unfocus (Display *xdisplay,
Window frame_xwindow,
int device_id,
guint32 timestamp);
void meta_core_user_focus (Display *xdisplay,
@ -118,6 +119,7 @@ void meta_core_user_focus (Display *xdisplay,
void meta_core_lower_beneath_grab_window (Display *xdisplay,
Window xwindow,
int device_id,
guint32 timestamp);
void meta_core_minimize (Display *xdisplay,
@ -163,6 +165,7 @@ const char* meta_core_get_workspace_name_with_index (Display *xdisplay,
void meta_core_show_window_menu (Display *xdisplay,
Window frame_xwindow,
int device_id,
int root_x,
int root_y,
int button,
@ -175,6 +178,7 @@ void meta_core_get_menu_accelerator (MetaMenuOp menu_op,
gboolean meta_core_begin_grab_op (Display *xdisplay,
Window frame_xwindow,
int device_id,
MetaGrabOp op,
gboolean pointer_already_grabbed,
gboolean frame_action,
@ -184,18 +188,29 @@ gboolean meta_core_begin_grab_op (Display *xdisplay,
int root_x,
int root_y);
void meta_core_end_grab_op (Display *xdisplay,
int device_id,
guint32 timestamp);
MetaGrabOp meta_core_get_grab_op (Display *xdisplay);
Window meta_core_get_grab_frame (Display *xdisplay);
int meta_core_get_grab_button (Display *xdisplay);
MetaGrabOp meta_core_frame_has_grab (Display *xdisplay,
Window frame_xwindow,
gint *device_id,
gint *button_ret);
Window meta_core_get_frame (Display *xdisplay,
Window client_xwindow);
void meta_core_grab_buttons (Display *xdisplay,
Window frame_xwindow);
void meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
MetaCursor cursor);
void meta_core_set_screen_cursor (Display *xdisplay,
Window frame_on_screen,
int device_id,
MetaCursor cursor);
void meta_core_select_events (Display *xdisplay,
Window xwindow,
gint evmask,
gboolean preserve_old_mask);
/* Used because we ignore EnterNotify when a window is unmapped that
* really shouldn't cause focus changes, by comparing the event serial

View File

@ -108,11 +108,7 @@ delete_ping_timeout_func (MetaDisplay *display,
/* Translators: %s is a window title */
if (window_title)
{
char *title = g_strdup_printf ("“%s”", window_title);
tmp = g_strdup_printf (_("%s is not responding."), title);
g_free (title);
}
tmp = g_strdup_printf (_("“%s” is not responding."), window_title);
else
tmp = g_strdup (_("Application is not responding."));

View File

@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Keyboard device abstraction */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include <config.h>
#include "device-keyboard.h"
G_DEFINE_ABSTRACT_TYPE (MetaDeviceKeyboard,
meta_device_keyboard,
META_TYPE_DEVICE)
static void
meta_device_keyboard_class_init (MetaDeviceKeyboardClass *klass)
{
}
static void
meta_device_keyboard_init (MetaDeviceKeyboard *keyboard)
{
}
Window
meta_device_keyboard_get_focus_window (MetaDeviceKeyboard *keyboard)
{
MetaDeviceKeyboardClass *klass;
g_return_val_if_fail (META_IS_DEVICE_KEYBOARD (keyboard), None);
klass = META_DEVICE_KEYBOARD_GET_CLASS (keyboard);
if (!klass->get_focus_window)
return None;
return (klass->get_focus_window) (keyboard);
}
void
meta_device_keyboard_set_focus_window (MetaDeviceKeyboard *keyboard,
Window xwindow,
Time timestamp)
{
MetaDeviceKeyboardClass *klass;
g_return_if_fail (META_IS_DEVICE_KEYBOARD (keyboard));
klass = META_DEVICE_KEYBOARD_GET_CLASS (keyboard);
if (klass->set_focus_window)
(klass->set_focus_window) (keyboard, xwindow, timestamp);
}

View File

@ -0,0 +1,69 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file device-keyboard.h Keyboard device abstraction
*
* Input devices.
* This file contains the internal abstraction of keyboard devices so
* XInput2/core events can be handled similarly.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_KEYBOARD_H
#define META_DEVICE_KEYBOARD_H
#include "display-private.h"
#include "device-private.h"
#define META_TYPE_DEVICE_KEYBOARD (meta_device_keyboard_get_type ())
#define META_DEVICE_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_KEYBOARD, MetaDeviceKeyboard))
#define META_DEVICE_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_KEYBOARD, MetaDeviceKeyboardClass))
#define META_IS_DEVICE_KEYBOARD(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_KEYBOARD))
#define META_IS_DEVICE_KEYBOARD_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_KEYBOARD))
#define META_DEVICE_KEYBOARD_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_KEYBOARD, MetaDeviceKeyboardClass))
typedef struct _MetaDeviceKeyboard MetaDeviceKeyboard;
typedef struct _MetaDeviceKeyboardClass MetaDeviceKeyboardClass;
struct _MetaDeviceKeyboard
{
MetaDevice parent_instance;
};
struct _MetaDeviceKeyboardClass
{
MetaDeviceClass parent_instance;
Window (* get_focus_window) (MetaDeviceKeyboard *keyboard);
void (* set_focus_window) (MetaDeviceKeyboard *keyboard,
Window xwindow,
Time timestamp);
};
GType meta_device_keyboard_get_type (void) G_GNUC_CONST;
Window meta_device_keyboard_get_focus_window (MetaDeviceKeyboard *keyboard);
void meta_device_keyboard_set_focus_window (MetaDeviceKeyboard *keyboard,
Window xwindow,
Time timestamp);
#endif /* META_DEVICE_KEYBOARD_H */

134
src/core/device-map-core.c Normal file
View File

@ -0,0 +1,134 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Input device map, core protocol implementation */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include "config.h"
#include "device-map-core.h"
#include "devices-core.h"
G_DEFINE_TYPE (MetaDeviceMapCore, meta_device_map_core, META_TYPE_DEVICE_MAP)
static gboolean
meta_device_map_core_grab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers,
gboolean sync)
{
MetaDisplay *display;
gint retval;
display = meta_device_map_get_display (device_map);
retval = XGrabKey (display->xdisplay, keycode, modifiers,
xwindow, True,
GrabModeAsync, /* Never care about the other device */
(sync) ? GrabModeSync : GrabModeAsync);
return (retval == Success);
}
static void
meta_device_map_core_ungrab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers)
{
MetaDisplay *display;
display = meta_device_map_get_display (device_map);
XUngrabKey (display->xdisplay, keycode, modifiers, xwindow);
}
static gboolean
meta_device_map_core_grab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers,
guint evmask,
gboolean sync)
{
MetaDisplay *display;
gint retval;
display = meta_device_map_get_display (device_map);
retval = XGrabButton (display->xdisplay, n_button,
modifiers, xwindow, False,
evmask,
(sync) ? GrabModeSync : GrabModeAsync,
GrabModeAsync, /* Never care about the other device */
None, None);
return (retval == Success);
}
static void
meta_device_map_core_ungrab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers)
{
MetaDisplay *display;
display = meta_device_map_get_display (device_map);
XUngrabButton (display->xdisplay, n_button, modifiers, xwindow);
}
static void
meta_device_map_core_constructed (GObject *object)
{
MetaDeviceMap *device_map = META_DEVICE_MAP (object);
MetaDevice *pointer, *keyboard;
MetaDisplay *display;
display = meta_device_map_get_display (device_map);
/* Insert core devices */
pointer = meta_device_pointer_core_new (display);
meta_device_map_add_device (device_map, pointer);
keyboard = meta_device_keyboard_core_new (display);
meta_device_map_add_device (device_map, keyboard);
meta_device_pair_devices (pointer, keyboard);
g_object_unref (pointer);
g_object_unref (keyboard);
}
static void
meta_device_map_core_class_init (MetaDeviceMapCoreClass *klass)
{
MetaDeviceMapClass *device_map_class = META_DEVICE_MAP_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = meta_device_map_core_constructed;
device_map_class->grab_key = meta_device_map_core_grab_key;
device_map_class->ungrab_key = meta_device_map_core_ungrab_key;
device_map_class->grab_button = meta_device_map_core_grab_button;
device_map_class->ungrab_button = meta_device_map_core_ungrab_button;
}
static void
meta_device_map_core_init (MetaDeviceMapCore *device_map)
{
}

View File

@ -0,0 +1,56 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file device-map-core.h device map for core devices
*
* Input devices.
* This file contains the core protocol implementation of the device map
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_MAP_CORE_H
#define META_DEVICE_MAP_CORE_H
typedef struct _MetaDeviceMapCore MetaDeviceMapCore;
typedef struct _MetaDeviceMapCoreClass MetaDeviceMapCoreClass;
#include "device-map-private.h"
#define META_TYPE_DEVICE_MAP_CORE (meta_device_map_core_get_type ())
#define META_DEVICE_MAP_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCore))
#define META_DEVICE_MAP_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCoreClass))
#define META_IS_DEVICE_MAP_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP_CORE))
#define META_IS_DEVICE_MAP_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP_CORE))
#define META_DEVICE_MAP_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP_CORE, MetaDeviceMapCoreClass))
struct _MetaDeviceMapCore
{
MetaDeviceMap parent_instance;
};
struct _MetaDeviceMapCoreClass
{
MetaDeviceMapClass parent_class;
};
GType meta_device_map_core_get_type (void) G_GNUC_CONST;
#endif /* META_DEVICE_MAP_CORE_H */

View File

@ -0,0 +1,111 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file device-map.h object containing input devices
*
* Input devices.
* This file contains the device map, used to find out the device behind
* XInput2/core events.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_MAP_PRIVATE_H
#define META_DEVICE_MAP_PRIVATE_H
#include <meta/device-map.h>
#include <meta/device.h>
#include "display-private.h"
#include "device-private.h"
/* Device IDs for Virtual Core Pointer/Keyboard,
* use only in case of emergency.
*/
#define META_CORE_POINTER_ID 2
#define META_CORE_KEYBOARD_ID 3
struct _MetaDeviceMap
{
GObject parent_instance;
gpointer priv;
};
struct _MetaDeviceMapClass
{
GObjectClass parent_instance;
void (* device_added) (MetaDeviceMap *device_map,
MetaDevice *device);
void (* device_removed) (MetaDeviceMap *device_map,
MetaDevice *device);
gboolean (* grab_key) (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers,
gboolean sync);
void (* ungrab_key) (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers);
gboolean (* grab_button) (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers,
guint evmask,
gboolean sync);
void (* ungrab_button) (MetaDeviceMap *pointer,
Window xwindow,
guint n_button,
guint modifiers);
};
GType meta_device_map_get_type (void) G_GNUC_CONST;
MetaDeviceMap * meta_device_map_new (MetaDisplay *display,
gboolean force_core);
void meta_device_map_add_device (MetaDeviceMap *device_map,
MetaDevice *device);
void meta_device_map_remove_device (MetaDeviceMap *device_map,
MetaDevice *device);
gboolean meta_device_map_grab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers,
gboolean sync);
void meta_device_map_ungrab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers);
gboolean meta_device_map_grab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers,
guint evmask,
gboolean sync);
void meta_device_map_ungrab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers);
#endif /* META_DEVICE_MAP_PRIVATE_H */

269
src/core/device-map-xi2.c Normal file
View File

@ -0,0 +1,269 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Input device map, XInput2 implementation */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include "config.h"
#include "device-map-xi2.h"
#include <X11/extensions/XInput2.h>
#include "devices-xi2.h"
#define XINPUT2_VERSION_MAJOR 2
#define XINPUT2_VERSION_MINOR 2
G_DEFINE_TYPE (MetaDeviceMapXI2, meta_device_map_xi2, META_TYPE_DEVICE_MAP)
static gboolean
meta_device_map_xi2_grab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers,
gboolean sync)
{
XIGrabModifiers mods = { modifiers, 0 };
MetaDisplay *display;
XIEventMask mask;
gint retval;
display = meta_device_map_get_display (device_map);
mask.deviceid = XIAllMasterDevices;
mask.mask = meta_device_xi2_translate_event_mask (KeyPressMask |
KeyReleaseMask,
&mask.mask_len);
/* FIXME: Doesn't seem to work with
* XIAllMasterDevices, use the VCK
* at the moment
*/
retval = XIGrabKeycode (display->xdisplay,
META_CORE_KEYBOARD_ID,
keycode, xwindow,
(sync) ? GrabModeSync : GrabModeAsync,
GrabModeAsync, /* Never care about the other device */
True, &mask, 1, &mods);
return (retval == Success);
}
static void
meta_device_map_xi2_ungrab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers)
{
XIGrabModifiers mods = { modifiers, 0 };
MetaDisplay *display;
display = meta_device_map_get_display (device_map);
XIUngrabKeycode (display->xdisplay,
META_CORE_KEYBOARD_ID,
keycode, xwindow,
1, &mods);
}
static gboolean
meta_device_map_xi2_grab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers,
guint evmask,
gboolean sync)
{
XIGrabModifiers mods = { modifiers, 0 };
XIEventMask mask;
MetaDisplay *display;
int retval;
display = meta_device_map_get_display (device_map);
mask.deviceid = XIAllMasterDevices;
mask.mask = meta_device_xi2_translate_event_mask (evmask, &mask.mask_len);
retval = XIGrabButton (display->xdisplay,
XIAllMasterDevices,
n_button, xwindow, None,
(sync) ? GrabModeSync : GrabModeAsync,
GrabModeAsync, /* Never care about the other device */
False, &mask, 1, &mods);
return (retval == Success);
}
static void
meta_device_map_xi2_ungrab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers)
{
XIGrabModifiers mods = { modifiers, 0 };
MetaDisplay *display;
display = meta_device_map_get_display (device_map);
XIUngrabButton (display->xdisplay,
META_CORE_POINTER_ID,
//XIAllMasterDevices,
n_button, xwindow, 1, &mods);
}
static void
add_device_from_info (MetaDeviceMap *device_map,
gint use,
gint device_id)
{
MetaDevice *device;
MetaDisplay *display;
display = meta_device_map_get_display (device_map);
if (use == XIMasterPointer)
device = meta_device_pointer_xi2_new (display, device_id);
else if (use == XIMasterKeyboard)
device = meta_device_keyboard_xi2_new (display, device_id);
if (device)
{
meta_device_map_add_device (device_map, device);
g_object_unref (device);
}
}
static void
pair_devices (gpointer key,
gpointer value,
gpointer user_data)
{
MetaDevice *device1, *device2;
MetaDeviceMap *device_map;
device_map = user_data;
device1 = meta_device_map_lookup (device_map, GPOINTER_TO_INT (key));
device2 = meta_device_map_lookup (device_map, GPOINTER_TO_INT (value));
meta_device_pair_devices (device1, device2);
}
static void
meta_device_map_xi2_constructed (GObject *object)
{
MetaDeviceMap *device_map = META_DEVICE_MAP (object);
MetaDisplay *display;
XIDeviceInfo *info;
GHashTable *pairs;
int n_devices, i;
display = meta_device_map_get_display (device_map);
/* We're only interested in master devices,
* detached slave devices are left for applications
* to handle.
*/
info = XIQueryDevice (display->xdisplay, XIAllMasterDevices, &n_devices);
pairs = g_hash_table_new (NULL, NULL);
for (i = 0; i < n_devices; i++)
{
add_device_from_info (device_map, info[i].use, info[i].deviceid);
g_hash_table_insert (pairs,
GINT_TO_POINTER (info[i].deviceid),
GINT_TO_POINTER (info[i].attachment));
}
g_hash_table_foreach (pairs, pair_devices, device_map);
g_hash_table_destroy (pairs);
XIFreeDeviceInfo (info);
}
static void
meta_device_map_xi2_class_init (MetaDeviceMapXI2Class *klass)
{
MetaDeviceMapClass *device_map_class = META_DEVICE_MAP_CLASS (klass);
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->constructed = meta_device_map_xi2_constructed;
device_map_class->grab_key = meta_device_map_xi2_grab_key;
device_map_class->ungrab_key = meta_device_map_xi2_ungrab_key;
device_map_class->grab_button = meta_device_map_xi2_grab_button;
device_map_class->ungrab_button = meta_device_map_xi2_ungrab_button;
}
static void
meta_device_map_xi2_init (MetaDeviceMapXI2 *device_map)
{
}
gboolean
meta_device_map_xi2_handle_hierarchy_event (MetaDeviceMapXI2 *device_map,
XEvent *ev)
{
MetaDisplay *display;
display = meta_device_map_get_display (META_DEVICE_MAP (device_map));
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIHierarchyEvent *xev;
GHashTable *pairs;
gint i;
g_assert (display->have_xinput2 == TRUE);
xev = (XIHierarchyEvent *) ev->xcookie.data;
if (xev->evtype != XI_HierarchyChanged)
return FALSE;
pairs = g_hash_table_new (NULL, NULL);
for (i = 0; i < xev->num_info; i++)
{
if (xev->info[i].flags & XIMasterAdded)
{
add_device_from_info (META_DEVICE_MAP (device_map),
xev->info[i].use,
xev->info[i].deviceid);
g_hash_table_insert (pairs,
GINT_TO_POINTER (xev->info[i].deviceid),
GINT_TO_POINTER (xev->info[i].attachment));
}
else if (xev->info[i].flags & XIMasterRemoved)
{
MetaDevice *device;
device = meta_device_map_lookup (META_DEVICE_MAP (device_map),
xev->info[i].deviceid);
if (device)
meta_device_map_remove_device (META_DEVICE_MAP (device_map),
device);
}
}
g_hash_table_foreach (pairs, pair_devices, device_map);
g_hash_table_destroy (pairs);
return TRUE;
}
return FALSE;
}

59
src/core/device-map-xi2.h Normal file
View File

@ -0,0 +1,59 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file device-map-xi2.h device map for XInput2 devices
*
* Input devices.
* This file contains the XInput2 implementation of the device map
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_MAP_XI2_H
#define META_DEVICE_MAP_XI2_H
typedef struct _MetaDeviceMapXI2 MetaDeviceMapXI2;
typedef struct _MetaDeviceMapXI2Class MetaDeviceMapXI2Class;
#include "device-map-private.h"
#define META_TYPE_DEVICE_MAP_XI2 (meta_device_map_xi2_get_type ())
#define META_DEVICE_MAP_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2))
#define META_DEVICE_MAP_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2Class))
#define META_IS_DEVICE_MAP_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP_XI2))
#define META_IS_DEVICE_MAP_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP_XI2))
#define META_DEVICE_MAP_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP_XI2, MetaDeviceMapXI2Class))
struct _MetaDeviceMapXI2
{
MetaDeviceMap parent_instance;
};
struct _MetaDeviceMapXI2Class
{
MetaDeviceMapClass parent_class;
};
GType meta_device_map_xi2_get_type (void) G_GNUC_CONST;
gboolean meta_device_map_xi2_handle_hierarchy_event (MetaDeviceMapXI2 *device_map,
XEvent *ev);
#endif /* META_DEVICE_MAP_XI2_H */

390
src/core/device-map.c Normal file
View File

@ -0,0 +1,390 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Input device map */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include "config.h"
#include "device-map-private.h"
#include "device-map-core.h"
#ifdef HAVE_XINPUT2
#include <X11/extensions/XInput2.h>
#include "device-map-xi2.h"
#define XINPUT2_VERSION_MAJOR 2
#define XINPUT2_VERSION_MINOR 2
#endif
G_DEFINE_TYPE (MetaDeviceMap, meta_device_map, G_TYPE_OBJECT)
typedef struct MetaDeviceMapPrivate MetaDeviceMapPrivate;
struct MetaDeviceMapPrivate
{
MetaDisplay *display;
GHashTable *devices;
};
enum {
PROP_0,
PROP_DISPLAY
};
enum {
DEVICE_ADDED,
DEVICE_REMOVED,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL] = { 0 };
static void
meta_device_map_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
MetaDeviceMapPrivate *priv;
priv = META_DEVICE_MAP (object)->priv;
switch (param_id)
{
case PROP_DISPLAY:
g_value_set_object (value, priv->display);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
static void
meta_device_map_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
MetaDeviceMapPrivate *priv;
priv = META_DEVICE_MAP (object)->priv;
switch (param_id)
{
case PROP_DISPLAY:
priv->display = g_value_get_object (value);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
static void
meta_device_map_finalize (GObject *object)
{
MetaDeviceMapPrivate *priv;
GHashTableIter iter;
MetaDevice *device;
priv = META_DEVICE_MAP (object)->priv;
g_hash_table_iter_init (&iter, priv->devices);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &device))
{
/* Detach the device */
g_hash_table_iter_steal (&iter);
g_signal_emit (object, signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
}
g_hash_table_destroy (priv->devices);
G_OBJECT_CLASS (meta_device_map_parent_class)->finalize (object);
}
static void
meta_device_map_class_init (MetaDeviceMapClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = meta_device_map_get_property;
object_class->set_property = meta_device_map_set_property;
object_class->finalize = meta_device_map_finalize;
g_object_class_install_property (object_class,
PROP_DISPLAY,
g_param_spec_object ("display",
"Display",
"Display",
META_TYPE_DISPLAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
signals[DEVICE_ADDED] =
g_signal_new ("device-added",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_DEVICE);
signals[DEVICE_REMOVED] =
g_signal_new ("device-removed",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST,
0,
NULL, NULL,
g_cclosure_marshal_VOID__OBJECT,
G_TYPE_NONE, 1, META_TYPE_DEVICE);
g_type_class_add_private (klass, sizeof (MetaDeviceMapPrivate));
}
static void
meta_device_map_init (MetaDeviceMap *device_map)
{
MetaDeviceMapPrivate *priv;
priv = device_map->priv = G_TYPE_INSTANCE_GET_PRIVATE (device_map,
META_TYPE_DEVICE_MAP,
MetaDeviceMapPrivate);
priv->devices = g_hash_table_new_full (NULL, NULL, NULL,
(GDestroyNotify) g_object_unref);
}
void
meta_device_map_add_device (MetaDeviceMap *device_map,
MetaDevice *device)
{
MetaDeviceMapPrivate *priv;
priv = device_map->priv;
g_hash_table_insert (priv->devices,
GINT_TO_POINTER (meta_device_get_id (device)),
g_object_ref (device));
g_signal_emit (device_map, signals[DEVICE_ADDED], 0, device);
}
void
meta_device_map_remove_device (MetaDeviceMap *device_map,
MetaDevice *device)
{
MetaDeviceMapPrivate *priv;
priv = device_map->priv;
if (g_hash_table_steal (priv->devices,
GINT_TO_POINTER (meta_device_get_id (device))))
{
g_signal_emit (device_map, signals[DEVICE_REMOVED], 0, device);
g_object_unref (device);
}
}
#ifdef HAVE_XINPUT2
static gboolean
initialize_xinput (MetaDisplay *display)
{
int major, minor, opcode;
int unused;
if (!XQueryExtension (display->xdisplay,
"XInputExtension",
&opcode, &unused, &unused))
return FALSE;
major = XINPUT2_VERSION_MAJOR;
minor = XINPUT2_VERSION_MINOR;
XIQueryVersion (display->xdisplay, &major, &minor);
if (major == XINPUT2_VERSION_MAJOR &&
minor == XINPUT2_VERSION_MINOR)
{
display->have_xinput2 = TRUE;
display->xinput2_opcode = opcode;
return TRUE;
}
return FALSE;
}
#endif /* HAVE_XINPUT2 */
MetaDeviceMap *
meta_device_map_new (MetaDisplay *display,
gboolean force_core)
{
GType type = META_TYPE_DEVICE_MAP_CORE;
#ifdef HAVE_XINPUT2
if (!force_core &&
initialize_xinput (display))
type = META_TYPE_DEVICE_MAP_XI2;
#endif
return g_object_new (type,
"display", display,
NULL);
}
/**
* meta_device_map_lookup:
* @device_map: a #MetaDeviceMap
* @device_id: ID for a device
*
* returns the device corresponding to @device_id
*
* Returns: (transfer none): (allow-none): The matching device, or %NULL.
**/
MetaDevice *
meta_device_map_lookup (MetaDeviceMap *device_map,
gint device_id)
{
MetaDeviceMapPrivate *priv;
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL);
priv = device_map->priv;
return g_hash_table_lookup (priv->devices,
GINT_TO_POINTER (device_id));
}
/**
* meta_device_map_get_display:
* @device_map: a #MetaDeviceMap
*
* Returns the #MetaDisplay to which @device_map belongs to.
*
* Returns: (transfer none): The #MetaDisplay.
**/
MetaDisplay *
meta_device_map_get_display (MetaDeviceMap *device_map)
{
MetaDeviceMapPrivate *priv;
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL);
priv = device_map->priv;
return priv->display;
}
/**
* meta_device_map_list_devices:
* @device_map: a #MetaDeviceMap
*
* Returns the list of devices that @device_map holds.
*
* Returns: (element-type Meta.Device) (transfer container): the list
* of devices, the contained objects are owned by @device_map
* and should not be unref'ed. The list must be freed with
* g_list_free().
**/
GList *
meta_device_map_list_devices (MetaDeviceMap *device_map)
{
MetaDeviceMapPrivate *priv;
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), NULL);
priv = device_map->priv;
return g_hash_table_get_values (priv->devices);
}
gboolean
meta_device_map_grab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers,
gboolean sync)
{
MetaDeviceMapClass *klass;
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), FALSE);
g_return_val_if_fail (xwindow != None, FALSE);
klass = META_DEVICE_MAP_GET_CLASS (device_map);
if (!klass->grab_key)
return FALSE;
return (klass->grab_key) (device_map, xwindow, keycode, modifiers, sync);
}
void
meta_device_map_ungrab_key (MetaDeviceMap *device_map,
Window xwindow,
guint keycode,
guint modifiers)
{
MetaDeviceMapClass *klass;
g_return_if_fail (META_IS_DEVICE_MAP (device_map));
g_return_if_fail (xwindow != None);
klass = META_DEVICE_MAP_GET_CLASS (device_map);
if (klass->ungrab_key)
(klass->ungrab_key) (device_map, xwindow, keycode, modifiers);
}
gboolean
meta_device_map_grab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers,
guint evmask,
gboolean sync)
{
MetaDeviceMapClass *klass;
g_return_val_if_fail (META_IS_DEVICE_MAP (device_map), FALSE);
g_return_val_if_fail (xwindow != None, FALSE);
klass = META_DEVICE_MAP_GET_CLASS (device_map);
if (!klass->grab_button)
return FALSE;
return (klass->grab_button) (device_map, xwindow, n_button,
modifiers, evmask, sync);
}
void
meta_device_map_ungrab_button (MetaDeviceMap *device_map,
Window xwindow,
guint n_button,
guint modifiers)
{
MetaDeviceMapClass *klass;
g_return_if_fail (META_IS_DEVICE_MAP (device_map));
g_return_if_fail (xwindow != None);
klass = META_DEVICE_MAP_GET_CLASS (device_map);
if (klass->ungrab_button)
(klass->ungrab_button) (device_map, xwindow, n_button, modifiers);
}

124
src/core/device-pointer.c Normal file
View File

@ -0,0 +1,124 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Pointer device abstraction */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include <config.h>
#include "device-pointer.h"
G_DEFINE_ABSTRACT_TYPE (MetaDevicePointer,
meta_device_pointer,
META_TYPE_DEVICE)
static void
meta_device_pointer_class_init (MetaDevicePointerClass *klass)
{
}
static void
meta_device_pointer_init (MetaDevicePointer *pointer)
{
}
void
meta_device_pointer_warp (MetaDevicePointer *pointer,
MetaScreen *screen,
gint x,
gint y)
{
MetaDevicePointerClass *klass;
g_return_if_fail (META_IS_DEVICE_POINTER (pointer));
g_return_if_fail (META_IS_SCREEN (screen));
klass = META_DEVICE_POINTER_GET_CLASS (pointer);
if (klass->warp)
(klass->warp) (pointer, screen, x, y);
}
void
meta_device_pointer_set_window_cursor (MetaDevicePointer *pointer,
Window xwindow,
MetaCursor cursor)
{
MetaDevicePointerClass *klass;
g_return_if_fail (META_IS_DEVICE_POINTER (pointer));
g_return_if_fail (xwindow != None);
klass = META_DEVICE_POINTER_GET_CLASS (pointer);
if (klass->set_window_cursor)
(klass->set_window_cursor) (pointer, xwindow, cursor);
}
gboolean
meta_device_pointer_query_position (MetaDevicePointer *pointer,
Window xwindow,
Window *root_ret,
Window *child_ret,
gint *root_x_ret,
gint *root_y_ret,
gint *x_ret,
gint *y_ret,
guint *mask_ret)
{
MetaDevicePointerClass *klass;
gint root_x, root_y, x, y;
Window root, child;
gboolean retval;
guint mask;
g_return_val_if_fail (META_IS_DEVICE_POINTER (pointer), FALSE);
g_return_val_if_fail (xwindow != None, FALSE);
klass = META_DEVICE_POINTER_GET_CLASS (pointer);
if (!klass->query_position)
return FALSE;
retval = (klass->query_position) (pointer, xwindow, &root, &child,
&root_x, &root_y, &x, &y, &mask);
if (root_ret)
*root_ret = root;
if (child_ret)
*child_ret = child;
if (root_x_ret)
*root_x_ret = root_x;
if (root_y_ret)
*root_y_ret = root_y;
if (x_ret)
*x_ret = x;
if (y_ret)
*y_ret = y;
if (mask_ret)
*mask_ret = mask;
return retval;
}

95
src/core/device-pointer.h Normal file
View File

@ -0,0 +1,95 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file device-pointer.h Pointer device abstraction
*
* Input devices.
* This file contains the internal abstraction of pointer devices so
* XInput2/core events can be handled similarly.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_POINTER_H
#define META_DEVICE_POINTER_H
#include "display-private.h"
#include <meta/screen.h>
#include "device-private.h"
#define META_TYPE_DEVICE_POINTER (meta_device_pointer_get_type ())
#define META_DEVICE_POINTER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER, MetaDevicePointer))
#define META_DEVICE_POINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_POINTER, MetaDevicePointerClass))
#define META_IS_DEVICE_POINTER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_POINTER))
#define META_IS_DEVICE_POINTER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_POINTER))
#define META_DEVICE_POINTER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_POINTER, MetaDevicePointerClass))
typedef struct _MetaDevicePointer MetaDevicePointer;
typedef struct _MetaDevicePointerClass MetaDevicePointerClass;
struct _MetaDevicePointer
{
MetaDevice parent_instance;
};
struct _MetaDevicePointerClass
{
MetaDeviceClass parent_instance;
void (* warp) (MetaDevicePointer *pointer,
MetaScreen *screen,
gint x,
gint y);
void (* set_window_cursor) (MetaDevicePointer *pointer,
Window xwindow,
MetaCursor cursor);
gboolean (* query_position) (MetaDevicePointer *pointer,
Window xwindow,
Window *root,
Window *child,
gint *root_x,
gint *root_y,
gint *x,
gint *y,
guint *mask);
};
GType meta_device_pointer_get_type (void) G_GNUC_CONST;
void meta_device_pointer_warp (MetaDevicePointer *pointer,
MetaScreen *screen,
gint x,
gint y);
void meta_device_pointer_set_window_cursor (MetaDevicePointer *pointer,
Window xwindow,
MetaCursor cursor);
gboolean meta_device_pointer_query_position (MetaDevicePointer *pointer,
Window xwindow,
Window *root,
Window *child,
gint *root_x,
gint *root_y,
gint *x,
gint *y,
guint *mask);
#endif /* META_DEVICE_POINTER_H */

80
src/core/device-private.h Normal file
View File

@ -0,0 +1,80 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file device.h Input device abstraction
*
* Input devices.
* This file contains the internal abstraction of input devices so
* XInput2/core events can be handled similarly.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_PRIVATE_H
#define META_DEVICE_PRIVATE_H
#include <meta/device.h>
#include "display-private.h"
struct _MetaDevice
{
GObject parent_instance;
gpointer priv;
};
struct _MetaDeviceClass
{
GObjectClass parent_instance;
void (* allow_events) (MetaDevice *device,
int mode,
Time time);
gboolean (* grab) (MetaDevice *device,
Window xwindow,
guint evmask,
MetaCursor cursor,
gboolean owner_events,
gboolean sync,
Time time);
void (* ungrab) (MetaDevice *device,
Time time);
};
GType meta_device_get_type (void) G_GNUC_CONST;
void meta_device_allow_events (MetaDevice *device,
int mode,
Time time);
gboolean meta_device_grab (MetaDevice *device,
Window xwindow,
guint evmask,
MetaCursor cursor,
gboolean owner_events,
gboolean sync,
Time time);
void meta_device_ungrab (MetaDevice *device,
Time time);
void meta_device_pair_devices (MetaDevice *device,
MetaDevice *other_device);
#endif /* META_DEVICE_PRIVATE_H */

270
src/core/device.c Normal file
View File

@ -0,0 +1,270 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Input device abstraction */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include <config.h>
#include "device-private.h"
G_DEFINE_ABSTRACT_TYPE (MetaDevice, meta_device, G_TYPE_OBJECT)
enum {
PROP_0,
PROP_DEVICE_ID,
PROP_DISPLAY,
PROP_PAIRED_DEVICE
};
typedef struct MetaDevicePrivate MetaDevicePrivate;
struct MetaDevicePrivate
{
MetaDisplay *display;
MetaDevice *paired_device;
gint device_id;
};
static void
meta_device_get_property (GObject *object,
guint param_id,
GValue *value,
GParamSpec *pspec)
{
switch (param_id)
{
case PROP_DEVICE_ID:
g_value_set_int (value,
meta_device_get_id (META_DEVICE (object)));
break;
case PROP_DISPLAY:
g_value_set_object (value,
meta_device_get_display (META_DEVICE (object)));
break;
case PROP_PAIRED_DEVICE:
g_value_set_object (value,
meta_device_get_paired_device (META_DEVICE (object)));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
static void
meta_device_set_property (GObject *object,
guint param_id,
const GValue *value,
GParamSpec *pspec)
{
MetaDevicePrivate *priv = META_DEVICE (object)->priv;
switch (param_id)
{
case PROP_DEVICE_ID:
priv->device_id = g_value_get_int (value);
break;
case PROP_DISPLAY:
priv->display = g_value_get_object (value);
break;
case PROP_PAIRED_DEVICE:
meta_device_pair_devices (META_DEVICE (object),
g_value_get_object (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
break;
}
}
static void
meta_device_class_init (MetaDeviceClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
object_class->get_property = meta_device_get_property;
object_class->set_property = meta_device_set_property;
g_object_class_install_property (object_class,
PROP_DEVICE_ID,
g_param_spec_int ("device-id",
"Device ID",
"Device ID",
2, G_MAXINT, 2,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_DISPLAY,
g_param_spec_object ("display",
"Display",
"Display",
META_TYPE_DISPLAY,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_PAIRED_DEVICE,
g_param_spec_object ("paired-device",
"Paired device",
"Paired device",
META_TYPE_DEVICE,
G_PARAM_READWRITE));
g_type_class_add_private (klass, sizeof (MetaDevicePrivate));
}
static void
meta_device_init (MetaDevice *device)
{
device->priv = G_TYPE_INSTANCE_GET_PRIVATE (device,
META_TYPE_DEVICE,
MetaDevicePrivate);
}
int
meta_device_get_id (MetaDevice *device)
{
MetaDevicePrivate *priv;
g_return_val_if_fail (META_IS_DEVICE (device), 0);
priv = device->priv;
return priv->device_id;
}
/**
* meta_device_get_display:
* @device: a #MetaDevice
*
* Returns the #MetaDisplay to which the device belongs
*
* Returns: (transfer none): the #MetaDisplay to which the device belongs
**/
MetaDisplay *
meta_device_get_display (MetaDevice *device)
{
MetaDevicePrivate *priv;
g_return_val_if_fail (META_IS_DEVICE (device), NULL);
priv = device->priv;
return priv->display;
}
void
meta_device_allow_events (MetaDevice *device,
int mode,
Time time)
{
MetaDeviceClass *klass;
g_return_if_fail (META_IS_DEVICE (device));
klass = META_DEVICE_GET_CLASS (device);
if (klass->allow_events)
(klass->allow_events) (device, mode, time);
}
gboolean
meta_device_grab (MetaDevice *device,
Window xwindow,
guint evmask,
MetaCursor cursor,
gboolean owner_events,
gboolean sync,
Time time)
{
MetaDeviceClass *klass;
g_return_val_if_fail (META_IS_DEVICE (device), FALSE);
g_return_val_if_fail (xwindow != None, FALSE);
klass = META_DEVICE_GET_CLASS (device);
if (!klass->grab)
return FALSE;
return (klass->grab) (device, xwindow, evmask, cursor,
owner_events, sync, time);
}
void
meta_device_ungrab (MetaDevice *device,
Time time)
{
MetaDeviceClass *klass;
g_return_if_fail (META_IS_DEVICE (device));
klass = META_DEVICE_GET_CLASS (device);
if (klass->ungrab)
(klass->ungrab) (device, time);
}
void
meta_device_pair_devices (MetaDevice *device,
MetaDevice *other_device)
{
MetaDevicePrivate *priv1, *priv2;
g_return_if_fail (META_IS_DEVICE (device));
g_return_if_fail (META_IS_DEVICE (other_device));
priv1 = device->priv;
priv2 = other_device->priv;
/* Consider safe multiple calls
* on already paired devices
*/
if (priv1->paired_device != NULL &&
priv2->paired_device != NULL &&
priv1->paired_device == other_device &&
priv2->paired_device == device)
return;
g_return_if_fail (priv1->paired_device == NULL);
g_return_if_fail (priv2->paired_device == NULL);
priv1->paired_device = g_object_ref (other_device);
priv2->paired_device = g_object_ref (device);
g_object_notify (G_OBJECT (device), "paired-device");
g_object_notify (G_OBJECT (other_device), "paired-device");
}
/**
* meta_device_get_paired_device:
* @device: a #MetaDevice
*
* Returns the paired device. Devices come in keyboard/pointer pairs.
*
* Returns: (transfer none): The paired device.
**/
MetaDevice *
meta_device_get_paired_device (MetaDevice *device)
{
MetaDevicePrivate *priv;
g_return_val_if_fail (META_IS_DEVICE (device), NULL);
priv = device->priv;
return priv->paired_device;
}

256
src/core/devices-core.c Normal file
View File

@ -0,0 +1,256 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* Core input devices implementation */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include <config.h>
#include "screen-private.h"
#include "devices-core.h"
#include "device-map-private.h"
/* Common functions */
static void
meta_device_core_common_allow_events (MetaDevice *device,
int mode,
Time time)
{
MetaDisplay *display;
display = meta_device_get_display (device);
XAllowEvents (display->xdisplay, mode, time);
}
/* Core pointer */
G_DEFINE_TYPE (MetaDevicePointerCore,
meta_device_pointer_core,
META_TYPE_DEVICE_POINTER)
static gboolean
meta_device_pointer_core_grab (MetaDevice *device,
Window xwindow,
guint evmask,
MetaCursor cursor,
gboolean owner_events,
gboolean sync,
Time time)
{
MetaDisplay *display;
Cursor xcursor;
int retval;
display = meta_device_get_display (device);
xcursor = meta_display_create_x_cursor (display, cursor);
retval = XGrabPointer (display->xdisplay,
xwindow, owner_events,
evmask,
(sync) ? GrabModeSync : GrabModeAsync,
(sync) ? GrabModeSync : GrabModeAsync,
None, xcursor, time);
if (xcursor != None)
XFreeCursor (display->xdisplay, xcursor);
return (retval == Success);
}
static void
meta_device_pointer_core_ungrab (MetaDevice *device,
Time time)
{
MetaDisplay *display;
display = meta_device_get_display (device);
XUngrabPointer (display->xdisplay, time);
}
static void
meta_device_pointer_core_warp (MetaDevicePointer *pointer,
MetaScreen *screen,
gint x,
gint y)
{
MetaDisplay *display;
display = meta_device_get_display (META_DEVICE (pointer));
XWarpPointer (display->xdisplay,
None, screen->xroot,
0, 0, 0, 0, x, y);
}
static void
meta_device_pointer_core_set_window_cursor (MetaDevicePointer *pointer,
Window xwindow,
MetaCursor cursor)
{
MetaDisplay *display;
Cursor xcursor;
display = meta_device_get_display (META_DEVICE (pointer));
xcursor = meta_display_create_x_cursor (display, cursor);
XDefineCursor (display->xdisplay, xwindow, xcursor);
if (xcursor != None)
XFreeCursor (display->xdisplay, xcursor);
}
static gboolean
meta_device_pointer_core_query_position (MetaDevicePointer *pointer,
Window xwindow,
Window *root,
Window *child,
gint *root_x,
gint *root_y,
gint *x,
gint *y,
guint *mask)
{
MetaDisplay *display;
display = meta_device_get_display (META_DEVICE (pointer));
return XQueryPointer (display->xdisplay, xwindow,
root, child, root_x, root_y,
x, y, mask);
}
static void
meta_device_pointer_core_class_init (MetaDevicePointerCoreClass *klass)
{
MetaDevicePointerClass *pointer_class = META_DEVICE_POINTER_CLASS (klass);
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
device_class->allow_events = meta_device_core_common_allow_events;
device_class->grab = meta_device_pointer_core_grab;
device_class->ungrab = meta_device_pointer_core_ungrab;
pointer_class->warp = meta_device_pointer_core_warp;
pointer_class->set_window_cursor = meta_device_pointer_core_set_window_cursor;
pointer_class->query_position = meta_device_pointer_core_query_position;
}
static void
meta_device_pointer_core_init (MetaDevicePointerCore *pointer)
{
}
MetaDevice *
meta_device_pointer_core_new (MetaDisplay *display)
{
return g_object_new (META_TYPE_DEVICE_POINTER_CORE,
"device-id", META_CORE_POINTER_ID,
"display", display,
NULL);
}
/* Core Keyboard */
G_DEFINE_TYPE (MetaDeviceKeyboardCore,
meta_device_keyboard_core,
META_TYPE_DEVICE_KEYBOARD)
static gboolean
meta_device_keyboard_core_grab (MetaDevice *device,
Window xwindow,
guint evmask,
MetaCursor cursor,
gboolean owner_events,
gboolean sync,
Time time)
{
MetaDisplay *display;
gint retval;
display = meta_device_get_display (device);
retval = XGrabKeyboard (display->xdisplay, xwindow, owner_events,
(sync) ? GrabModeSync : GrabModeAsync,
(sync) ? GrabModeSync : GrabModeAsync,
time);
return (retval == Success);
}
static void
meta_device_keyboard_core_ungrab (MetaDevice *device,
Time time)
{
MetaDisplay *display;
display = meta_device_get_display (device);
XUngrabKeyboard (display->xdisplay, time);
}
static Window
meta_device_keyboard_core_get_focus_window (MetaDeviceKeyboard *keyboard)
{
MetaDisplay *display;
Window xwindow;
int unused;
display = meta_device_get_display (META_DEVICE (keyboard));
XGetInputFocus (display->xdisplay, &xwindow, &unused);
return xwindow;
}
static void
meta_device_keyboard_core_set_focus_window (MetaDeviceKeyboard *keyboard,
Window xwindow,
Time timestamp)
{
MetaDisplay *display;
display = meta_device_get_display (META_DEVICE (keyboard));
XSetInputFocus (display->xdisplay,
xwindow,
RevertToPointerRoot,
timestamp);
}
static void
meta_device_keyboard_core_class_init (MetaDeviceKeyboardCoreClass *klass)
{
MetaDeviceKeyboardClass *keyboard_class = META_DEVICE_KEYBOARD_CLASS (klass);
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
keyboard_class->get_focus_window = meta_device_keyboard_core_get_focus_window;
keyboard_class->set_focus_window = meta_device_keyboard_core_set_focus_window;
device_class->allow_events = meta_device_core_common_allow_events;
device_class->grab = meta_device_keyboard_core_grab;
device_class->ungrab = meta_device_keyboard_core_ungrab;
}
static void
meta_device_keyboard_core_init (MetaDeviceKeyboardCore *keyboard)
{
}
MetaDevice *
meta_device_keyboard_core_new (MetaDisplay *display)
{
return g_object_new (META_TYPE_DEVICE_KEYBOARD_CORE,
"device-id", META_CORE_KEYBOARD_ID,
"display", display,
NULL);
}

85
src/core/devices-core.h Normal file
View File

@ -0,0 +1,85 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file devices-core.h Core input devices implementation
*
* Input devices.
* This file contains the core X protocol implementation of input devices.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_CORE_H
#define META_DEVICES_CORE_H
#include "device-pointer.h"
#include "device-keyboard.h"
/* Pointer */
#define META_TYPE_DEVICE_POINTER_CORE (meta_device_pointer_core_get_type ())
#define META_DEVICE_POINTER_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCore))
#define META_DEVICE_POINTER_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCoreClass))
#define META_IS_DEVICE_POINTER_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_POINTER_CORE))
#define META_IS_DEVICE_POINTER_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_POINTER_CORE))
#define META_DEVICE_POINTER_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_POINTER_CORE, MetaDevicePointerCoreClass))
typedef struct _MetaDevicePointerCore MetaDevicePointerCore;
typedef struct _MetaDevicePointerCoreClass MetaDevicePointerCoreClass;
struct _MetaDevicePointerCore
{
MetaDevicePointer parent_instance;
};
struct _MetaDevicePointerCoreClass
{
MetaDevicePointerClass parent_class;
};
GType meta_device_pointer_core_get_type (void) G_GNUC_CONST;
MetaDevice *meta_device_pointer_core_new (MetaDisplay *display);
/* Keyboard */
#define META_TYPE_DEVICE_KEYBOARD_CORE (meta_device_keyboard_core_get_type ())
#define META_DEVICE_KEYBOARD_CORE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_KEYBOARD_CORE, MetaDeviceKeyboardCore))
#define META_DEVICE_KEYBOARD_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_KEYBOARD_CORE, MetaDeviceKeyboardCoreClass))
#define META_IS_DEVICE_KEYBOARD_CORE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_KEYBOARD_CORE))
#define META_IS_DEVICE_KEYBOARD_CORE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_KEYBOARD_CORE))
#define META_DEVICE_KEYBOARD_CORE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_KEYBOARD_CORE, MetaDeviceKeyboardCoreClass))
typedef struct _MetaDeviceKeyboardCore MetaDeviceKeyboardCore;
typedef struct _MetaDeviceKeyboardCoreClass MetaDeviceKeyboardCoreClass;
struct _MetaDeviceKeyboardCore
{
MetaDeviceKeyboard parent_instance;
};
struct _MetaDeviceKeyboardCoreClass
{
MetaDeviceKeyboardClass parent_class;
};
GType meta_device_keyboard_core_get_type (void) G_GNUC_CONST;
MetaDevice *meta_device_keyboard_core_new (MetaDisplay *display);
#endif /* META_DEVICES_CORE_H */

343
src/core/devices-xi2.c Normal file
View File

@ -0,0 +1,343 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* XInput2 devices implementation */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include <config.h>
#include "devices-xi2.h"
#include "display-private.h"
#include "screen-private.h"
#include <X11/extensions/XInput2.h>
/* Common functions */
static void
meta_device_xi2_common_allow_events (MetaDevice *device,
int mode,
Time time)
{
MetaDisplay *display;
gint device_id;
display = meta_device_get_display (device);
device_id = meta_device_get_id (device);
switch (mode)
{
case AsyncPointer:
case AsyncKeyboard:
mode = XIAsyncDevice;
break;
case SyncPointer:
case SyncKeyboard:
mode = XISyncDevice;
break;
case ReplayPointer:
case ReplayKeyboard:
mode = XIReplayDevice;
break;
case AsyncBoth:
mode = XIAsyncPair;
break;
case SyncBoth:
mode = XISyncPair;
break;
}
XIAllowEvents (display->xdisplay, device_id, mode, time);
}
guchar *
meta_device_xi2_translate_event_mask (guint evmask,
gint *len)
{
guchar *mask;
*len = XIMaskLen (XI_LASTEVENT);
mask = g_new0 (guchar, *len);
if (evmask & KeyPressMask)
XISetMask (mask, XI_KeyPress);
if (evmask & KeyReleaseMask)
XISetMask (mask, XI_KeyRelease);
if (evmask & ButtonPressMask)
XISetMask (mask, XI_ButtonPress);
if (evmask & ButtonReleaseMask)
XISetMask (mask, XI_ButtonRelease);
if (evmask & EnterWindowMask)
XISetMask (mask, XI_Enter);
if (evmask & LeaveWindowMask)
XISetMask (mask, XI_Leave);
/* No motion hints in XI2 at the moment... */
if (evmask & PointerMotionMask ||
evmask & PointerMotionHintMask)
XISetMask (mask, XI_Motion);
if (evmask & FocusChangeMask)
{
XISetMask (mask, XI_FocusIn);
XISetMask (mask, XI_FocusOut);
}
return mask;
}
static gboolean
meta_device_xi2_common_grab (MetaDevice *device,
Window xwindow,
guint evmask,
MetaCursor cursor,
gboolean owner_events,
gboolean sync,
Time time)
{
MetaDisplay *display;
XIEventMask mask;
gint device_id, retval;
Cursor xcursor;
display = meta_device_get_display (device);
device_id = meta_device_get_id (device);
xcursor = meta_display_create_x_cursor (display, cursor);
mask.deviceid = device_id;
mask.mask = meta_device_xi2_translate_event_mask (evmask, &mask.mask_len);
retval = XIGrabDevice (display->xdisplay,
device_id, xwindow,
time, xcursor,
(sync) ? GrabModeSync : GrabModeAsync,
(sync) ? GrabModeSync : GrabModeAsync,
owner_events, &mask);
if (xcursor != None)
XFreeCursor (display->xdisplay, xcursor);
return (retval == Success);
}
static void
meta_device_xi2_common_ungrab (MetaDevice *device,
Time time)
{
MetaDisplay *display;
gint device_id;
display = meta_device_get_display (device);
device_id = meta_device_get_id (device);
XIUngrabDevice (display->xdisplay, device_id, time);
}
/* Pointer */
G_DEFINE_TYPE (MetaDevicePointerXI2,
meta_device_pointer_xi2,
META_TYPE_DEVICE_POINTER)
static void
meta_device_pointer_xi2_warp (MetaDevicePointer *pointer,
MetaScreen *screen,
gint x,
gint y)
{
MetaDisplay *display;
int device_id;
display = meta_device_get_display (META_DEVICE (pointer));
device_id = meta_device_get_id (META_DEVICE (pointer));
XIWarpPointer (display->xdisplay,
device_id,
None, screen->xroot,
0, 0, 0, 0, x, y);
}
static void
meta_device_pointer_xi2_set_window_cursor (MetaDevicePointer *pointer,
Window xwindow,
MetaCursor cursor)
{
MetaDisplay *display;
Cursor xcursor;
int device_id;
display = meta_device_get_display (META_DEVICE (pointer));
device_id = meta_device_get_id (META_DEVICE (pointer));
xcursor = meta_display_create_x_cursor (display, cursor);
if (xcursor != None)
{
XIDefineCursor (display->xdisplay, device_id, xwindow, xcursor);
XFreeCursor (display->xdisplay, xcursor);
}
else
XIUndefineCursor (display->xdisplay, device_id, xwindow);
}
static gboolean
meta_device_pointer_xi2_query_position (MetaDevicePointer *pointer,
Window xwindow,
Window *root_ret,
Window *child_ret,
gint *root_x_ret,
gint *root_y_ret,
gint *x_ret,
gint *y_ret,
guint *mask_ret)
{
MetaDisplay *display;
XIModifierState mods;
XIGroupState group_unused;
XIButtonState buttons;
gdouble root_x, root_y, x, y;
int device_id;
gboolean retval;
display = meta_device_get_display (META_DEVICE (pointer));
device_id = meta_device_get_id (META_DEVICE (pointer));
retval = XIQueryPointer (display->xdisplay,
device_id, xwindow,
root_ret, child_ret,
&root_x, &root_y, &x, &y,
&buttons, &mods,
&group_unused);
if (mask_ret)
{
*mask_ret = mods.effective;
if (XIMaskIsSet (buttons.mask, 1))
*mask_ret |= Button1Mask;
else if (XIMaskIsSet (buttons.mask, 2))
*mask_ret |= Button2Mask;
else if (XIMaskIsSet (buttons.mask, 3))
*mask_ret |= Button3Mask;
}
if (root_x_ret)
*root_x_ret = (int) root_x;
if (root_y_ret)
*root_y_ret = (int) root_y;
if (x_ret)
*x_ret = (int) x;
if (y_ret)
*y_ret = (int) y;
return retval;
}
static void
meta_device_pointer_xi2_class_init (MetaDevicePointerXI2Class *klass)
{
MetaDevicePointerClass *pointer_class = META_DEVICE_POINTER_CLASS (klass);
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
device_class->allow_events = meta_device_xi2_common_allow_events;
device_class->grab = meta_device_xi2_common_grab;
device_class->ungrab = meta_device_xi2_common_ungrab;
pointer_class->warp = meta_device_pointer_xi2_warp;
pointer_class->set_window_cursor = meta_device_pointer_xi2_set_window_cursor;
pointer_class->query_position = meta_device_pointer_xi2_query_position;
}
static void
meta_device_pointer_xi2_init (MetaDevicePointerXI2 *pointer)
{
}
MetaDevice *
meta_device_pointer_xi2_new (MetaDisplay *display,
gint device_id)
{
return g_object_new (META_TYPE_DEVICE_POINTER_XI2,
"device-id", device_id,
"display", display,
NULL);
}
/* Keyboard */
G_DEFINE_TYPE (MetaDeviceKeyboardXI2,
meta_device_keyboard_xi2,
META_TYPE_DEVICE_KEYBOARD)
static Window
meta_device_keyboard_xi2_get_focus_window (MetaDeviceKeyboard *keyboard)
{
MetaDisplay *display;
Window xwindow;
display = meta_device_get_display (META_DEVICE (keyboard));
XIGetFocus (display->xdisplay,
meta_device_get_id (META_DEVICE (keyboard)),
&xwindow);
return xwindow;
}
static void
meta_device_keyboard_xi2_set_focus_window (MetaDeviceKeyboard *keyboard,
Window xwindow,
Time timestamp)
{
MetaDisplay *display;
display = meta_device_get_display (META_DEVICE (keyboard));
XISetFocus (display->xdisplay,
meta_device_get_id (META_DEVICE (keyboard)),
xwindow,
timestamp);
}
static void
meta_device_keyboard_xi2_class_init (MetaDeviceKeyboardXI2Class *klass)
{
MetaDeviceKeyboardClass *keyboard_class = META_DEVICE_KEYBOARD_CLASS (klass);
MetaDeviceClass *device_class = META_DEVICE_CLASS (klass);
keyboard_class->get_focus_window = meta_device_keyboard_xi2_get_focus_window;
keyboard_class->set_focus_window = meta_device_keyboard_xi2_set_focus_window;
device_class->allow_events = meta_device_xi2_common_allow_events;
device_class->grab = meta_device_xi2_common_grab;
device_class->ungrab = meta_device_xi2_common_ungrab;
}
static void
meta_device_keyboard_xi2_init (MetaDeviceKeyboardXI2 *keyboard)
{
}
MetaDevice *
meta_device_keyboard_xi2_new (MetaDisplay *display,
gint device_id)
{
return g_object_new (META_TYPE_DEVICE_KEYBOARD_XI2,
"device-id", device_id,
"display", display,
NULL);
}

92
src/core/devices-xi2.h Normal file
View File

@ -0,0 +1,92 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file devices-xi2.h XInput2 input devices implementation
*
* Input devices.
* This file contains the XInput2 implementation of input devices.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_XI2_H
#define META_DEVICES_XI2_H
#include "device-pointer.h"
#include "device-keyboard.h"
/* Pointer */
#define META_TYPE_DEVICE_POINTER_XI2 (meta_device_pointer_xi2_get_type ())
#define META_DEVICE_POINTER_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_POINTER_XI2, MetaDevicePointerXI2))
#define META_DEVICE_POINTER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_POINTER_XI2, MetaDevicePointerXI2Class))
#define META_IS_DEVICE_POINTER_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_POINTER_XI2))
#define META_IS_DEVICE_POINTER_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_POINTER_XI2))
#define META_DEVICE_POINTER_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_POINTER_XI2, MetaDevicePointerXI2Class))
typedef struct _MetaDevicePointerXI2 MetaDevicePointerXI2;
typedef struct _MetaDevicePointerXI2Class MetaDevicePointerXI2Class;
struct _MetaDevicePointerXI2
{
MetaDevicePointer parent_instance;
};
struct _MetaDevicePointerXI2Class
{
MetaDevicePointerClass parent_class;
};
GType meta_device_pointer_xi2_get_type (void) G_GNUC_CONST;
MetaDevice *meta_device_pointer_xi2_new (MetaDisplay *display,
gint device_id);
/* Keyboard */
#define META_TYPE_DEVICE_KEYBOARD_XI2 (meta_device_keyboard_xi2_get_type ())
#define META_DEVICE_KEYBOARD_XI2(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_KEYBOARD_XI2, MetaDeviceKeyboardXI2))
#define META_DEVICE_KEYBOARD_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_KEYBOARD_XI2, MetaDeviceKeyboardXI2Class))
#define META_IS_DEVICE_KEYBOARD_XI2(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_KEYBOARD_XI2))
#define META_IS_DEVICE_KEYBOARD_XI2_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_KEYBOARD_XI2))
#define META_DEVICE_KEYBOARD_XI2_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_KEYBOARD_XI2, MetaDeviceKeyboardXI2Class))
typedef struct _MetaDeviceKeyboardXI2 MetaDeviceKeyboardXI2;
typedef struct _MetaDeviceKeyboardXI2Class MetaDeviceKeyboardXI2Class;
struct _MetaDeviceKeyboardXI2
{
MetaDeviceKeyboard parent_instance;
};
struct _MetaDeviceKeyboardXI2Class
{
MetaDeviceKeyboardClass parent_class;
};
GType meta_device_keyboard_xi2_get_type (void) G_GNUC_CONST;
MetaDevice *meta_device_keyboard_xi2_new (MetaDisplay *display,
gint device_id);
/* Helper function for translating event masks */
guchar * meta_device_xi2_translate_event_mask (guint evmask,
gint *len);
#endif /* META_DEVICES_XI2_H */

View File

@ -38,6 +38,7 @@
#include <meta/boxes.h>
#include <meta/display.h>
#include "keybindings-private.h"
#include "device-map-private.h"
#include <meta/prefs.h>
#ifdef HAVE_STARTUP_NOTIFICATION
@ -56,6 +57,9 @@ typedef struct _MetaWindowPropHooks MetaWindowPropHooks;
typedef struct MetaEdgeResistanceData MetaEdgeResistanceData;
typedef struct _MetaGrabInfo MetaGrabInfo;
typedef struct _MetaFocusInfo MetaFocusInfo;
typedef void (* MetaWindowPingFunc) (MetaDisplay *display,
Window xwindow,
guint32 timestamp,
@ -86,6 +90,67 @@ typedef enum {
META_TILE_MAXIMIZED
} MetaTileMode;
struct _MetaGrabInfo
{
MetaDevice *grab_pointer;
MetaDevice *grab_keyboard;
MetaGrabOp grab_op;
MetaScreen *grab_screen;
MetaWindow *grab_window;
Window grab_xwindow;
int grab_button;
int grab_anchor_root_x;
int grab_anchor_root_y;
MetaRectangle grab_anchor_window_pos;
MetaTileMode grab_tile_mode;
int grab_tile_monitor_number;
int grab_latest_motion_x;
int grab_latest_motion_y;
gulong grab_mask;
guint grab_have_pointer : 1;
guint grab_have_keyboard : 1;
guint grab_frame_action : 1;
/* During a resize operation, the directions in which we've broken
* out of the initial maximization state */
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
MetaRectangle grab_initial_window_pos;
int grab_initial_x, grab_initial_y; /* These are only relevant for */
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time;
guint32 grab_motion_notify_time;
GList* grab_old_window_stacking;
unsigned int grab_last_user_action_was_snap;
MetaEdgeResistanceData *grab_edge_resistance_data;
#ifdef HAVE_XSYNC
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
XSyncAlarm grab_sync_request_alarm;
#endif
int grab_resize_timeout_id;
};
struct _MetaFocusInfo
{
/* This is the actual window from focus events,
* not the one we last set
*/
MetaWindow *focus_window;
/* window we are expecting a FocusIn event for or the current focus
* window if we are not expecting any FocusIn/FocusOut events; not
* perfect because applications can call XSetInputFocus directly.
* (It could also be messed up if a timestamp later than current
* time is sent to meta_display_set_input_focus_window, though that
* would be a programming error). See bug 154598 for more info.
*/
MetaWindow *expected_focus_window;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
};
struct _MetaDisplay
{
GObject parent_instance;
@ -104,22 +169,8 @@ struct _MetaDisplay
#include <meta/atomnames.h>
#undef item
/* This is the actual window from focus events,
* not the one we last set
*/
MetaWindow *focus_window;
/* window we are expecting a FocusIn event for or the current focus
* window if we are not expecting any FocusIn/FocusOut events; not
* perfect because applications can call XSetInputFocus directly.
* (It could also be messed up if a timestamp later than current
* time is sent to meta_display_set_input_focus_window, though that
* would be a programming error). See bug 154598 for more info.
*/
MetaWindow *expected_focus_window;
/* last timestamp passed to XSetInputFocus */
guint32 last_focus_time;
/* keyboard -> MetaFocusInfo hashtable */
GHashTable *focus_info;
/* last user interaction time in any app */
guint32 last_user_time;
@ -182,35 +233,11 @@ struct _MetaDisplay
/* Alt+click button grabs */
unsigned int window_grab_modifiers;
/* current window operation */
MetaGrabOp grab_op;
MetaScreen *grab_screen;
MetaWindow *grab_window;
Window grab_xwindow;
int grab_button;
int grab_anchor_root_x;
int grab_anchor_root_y;
MetaRectangle grab_anchor_window_pos;
MetaTileMode grab_tile_mode;
int grab_tile_monitor_number;
int grab_latest_motion_x;
int grab_latest_motion_y;
gulong grab_mask;
guint grab_have_pointer : 1;
guint grab_have_keyboard : 1;
guint grab_frame_action : 1;
/* During a resize operation, the directions in which we've broken
* out of the initial maximization state */
guint grab_resize_unmaximize : 2; /* MetaMaximizeFlags */
MetaRectangle grab_initial_window_pos;
int grab_initial_x, grab_initial_y; /* These are only relevant for */
gboolean grab_threshold_movement_reached; /* raise_on_click == FALSE. */
MetaResizePopup *grab_resize_popup;
GTimeVal grab_last_moveresize_time;
guint32 grab_motion_notify_time;
GList* grab_old_window_stacking;
MetaEdgeResistanceData *grab_edge_resistance_data;
unsigned int grab_last_user_action_was_snap;
/* per-device current window operation */
GHashTable *current_grabs;
/* per-screen edge resistance cache */
GHashTable *edge_resistance_info;
/* we use property updates as sentinels for certain window focus events
* to avoid some race conditions on EnterNotify events
@ -221,11 +248,6 @@ struct _MetaDisplay
int xkb_base_event_type;
guint32 last_bell_time;
#endif
#ifdef HAVE_XSYNC
/* alarm monitoring client's _NET_WM_SYNC_REQUEST_COUNTER */
XSyncAlarm grab_sync_request_alarm;
#endif
int grab_resize_timeout_id;
/* Keybindings stuff */
MetaKeyBinding *key_bindings;
@ -272,6 +294,9 @@ struct _MetaDisplay
/* Managed by compositor.c */
MetaCompositor *compositor;
/* Managed by device-map.c */
MetaDeviceMap *device_map;
int render_event_base;
int render_error_base;
@ -295,6 +320,12 @@ struct _MetaDisplay
int shape_event_base;
int shape_error_base;
#endif
#ifdef HAVE_XINPUT2
int xinput2_opcode;
unsigned int have_xinput2 : 1;
#endif
#ifdef HAVE_XSYNC
unsigned int have_xsync : 1;
#define META_DISPLAY_HAS_XSYNC(display) ((display)->have_xsync)
@ -380,12 +411,14 @@ Cursor meta_display_create_x_cursor (MetaDisplay *display,
void meta_display_set_grab_op_cursor (MetaDisplay *display,
MetaScreen *screen,
MetaDevice *device,
MetaGrabOp op,
gboolean change_pointer,
Window grab_xwindow,
guint32 timestamp);
void meta_display_check_threshold_reached (MetaDisplay *display,
MetaDevice *device,
int x,
int y);
void meta_display_grab_window_buttons (MetaDisplay *display,
@ -399,7 +432,8 @@ void meta_display_ungrab_focus_window_button (MetaDisplay *display,
MetaWindow *window);
/* Next function is defined in edge-resistance.c */
void meta_display_cleanup_edges (MetaDisplay *display);
void meta_display_cleanup_edges (MetaDisplay *display,
MetaScreen *screen);
/* make a request to ensure the event serial has changed */
void meta_display_increment_event_serial (MetaDisplay *display);
@ -447,4 +481,15 @@ void meta_display_overlay_key_activate (MetaDisplay *display);
/* In above-tab-keycode.c */
guint meta_display_get_above_tab_keycode (MetaDisplay *display);
MetaGrabInfo * meta_display_create_grab_info (MetaDisplay *display,
MetaDevice *device);
void meta_display_remove_grab_info (MetaDisplay *display,
MetaDevice *device);
MetaGrabInfo * meta_display_get_grab_info (MetaDisplay *display,
MetaDevice *device);
MetaFocusInfo * meta_display_get_focus_info (MetaDisplay *display,
MetaDevice *device);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -30,12 +30,12 @@
/* A simple macro for whether a given window's edges are potentially
* relevant for resistance/snapping during a move/resize operation
*/
#define WINDOW_EDGES_RELEVANT(window, display) \
meta_window_should_be_showing (window) && \
window->screen == display->grab_screen && \
window != display->grab_window && \
window->type != META_WINDOW_DESKTOP && \
window->type != META_WINDOW_MENU && \
#define WINDOW_EDGES_RELEVANT(window, display, screen) \
meta_window_should_be_showing (window) && \
window->screen == screen && \
window->cur_grab == NULL && \
window->type != META_WINDOW_DESKTOP && \
window->type != META_WINDOW_MENU && \
window->type != META_WINDOW_SPLASHSCREEN
struct ResistanceDataForAnEdge
@ -44,8 +44,9 @@ struct ResistanceDataForAnEdge
guint timeout_id;
int timeout_edge_pos;
gboolean timeout_over;
GSourceFunc timeout_func;
MetaEdgeResistanceFunc timeout_func;
MetaWindow *window;
MetaDevice *device;
int keyboard_buildup;
};
typedef struct ResistanceDataForAnEdge ResistanceDataForAnEdge;
@ -63,7 +64,9 @@ struct MetaEdgeResistanceData
ResistanceDataForAnEdge bottom_data;
};
static void compute_resistance_and_snapping_edges (MetaDisplay *display);
static MetaEdgeResistanceData *
compute_resistance_and_snapping_edges (MetaDisplay *display,
MetaScreen *screen);
/* !WARNING!: this function can return invalid indices (namely, either -1 or
* edges->len); this is by design, but you need to remember this.
@ -318,20 +321,22 @@ edge_resistance_timeout (gpointer data)
resistance_data->timeout_over = TRUE;
resistance_data->timeout_id = 0;
(*resistance_data->timeout_func)(resistance_data->window);
(*resistance_data->timeout_func) (resistance_data->window,
resistance_data->device);
return FALSE;
}
static int
apply_edge_resistance (MetaWindow *window,
MetaDevice *device,
int old_pos,
int new_pos,
const MetaRectangle *old_rect,
const MetaRectangle *new_rect,
GArray *edges,
ResistanceDataForAnEdge *resistance_data,
GSourceFunc timeout_func,
MetaEdgeResistanceFunc timeout_func,
gboolean xdir,
gboolean keyboard_op)
{
@ -445,6 +450,7 @@ apply_edge_resistance (MetaWindow *window,
resistance_data->timeout_over = FALSE;
resistance_data->timeout_func = timeout_func;
resistance_data->window = window;
resistance_data->device = device;
}
if (!resistance_data->timeout_over &&
timeout_length_ms != 0)
@ -533,29 +539,28 @@ apply_edge_snapping (int old_pos,
* a proposed new position (ignoring edge resistance/snapping), and then
* applies edge resistance to EACH edge (separately) updating new_outer.
* It returns true if new_outer is modified, false otherwise.
*
* display->grab_edge_resistance_data MUST already be setup or calling this
* function will cause a crash.
*/
static gboolean
apply_edge_resistance_to_each_side (MetaDisplay *display,
MetaWindow *window,
const MetaRectangle *old_outer,
MetaRectangle *new_outer,
GSourceFunc timeout_func,
gboolean auto_snap,
gboolean keyboard_op,
gboolean is_resize)
apply_edge_resistance_to_each_side (MetaDisplay *display,
MetaWindow *window,
MetaDevice *device,
const MetaRectangle *old_outer,
MetaRectangle *new_outer,
MetaEdgeResistanceFunc timeout_func,
gboolean auto_snap,
gboolean keyboard_op,
gboolean is_resize)
{
MetaEdgeResistanceData *edge_data;
MetaRectangle modified_rect;
gboolean modified;
int new_left, new_right, new_top, new_bottom;
if (display->grab_edge_resistance_data == NULL)
compute_resistance_and_snapping_edges (display);
edge_data = g_hash_table_lookup (display->edge_resistance_info,
window->screen);
edge_data = display->grab_edge_resistance_data;
if (!edge_data)
edge_data = compute_resistance_and_snapping_edges (display, window->screen);
if (auto_snap)
{
@ -601,7 +606,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
if (!is_resize || window->size_hints.width_inc == 1)
{
/* Now, apply the normal horizontal edge resistance */
new_left = apply_edge_resistance (window,
new_left = apply_edge_resistance (window, device,
BOX_LEFT (*old_outer),
BOX_LEFT (*new_outer),
old_outer,
@ -611,7 +616,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
timeout_func,
TRUE,
keyboard_op);
new_right = apply_edge_resistance (window,
new_right = apply_edge_resistance (window, device,
BOX_RIGHT (*old_outer),
BOX_RIGHT (*new_outer),
old_outer,
@ -630,7 +635,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
/* Same for vertical resizes... */
if (!is_resize || window->size_hints.height_inc == 1)
{
new_top = apply_edge_resistance (window,
new_top = apply_edge_resistance (window, device,
BOX_TOP (*old_outer),
BOX_TOP (*new_outer),
old_outer,
@ -640,7 +645,7 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
timeout_func,
FALSE,
keyboard_op);
new_bottom = apply_edge_resistance (window,
new_bottom = apply_edge_resistance (window, device,
BOX_BOTTOM (*old_outer),
BOX_BOTTOM (*new_outer),
old_outer,
@ -669,15 +674,20 @@ apply_edge_resistance_to_each_side (MetaDisplay *display,
}
void
meta_display_cleanup_edges (MetaDisplay *display)
meta_display_cleanup_edges (MetaDisplay *display,
MetaScreen *screen)
{
guint i,j;
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
MetaEdgeResistanceData *edge_data;
GHashTable *edges_to_be_freed;
edge_data = g_hash_table_lookup (display->edge_resistance_info, screen);
if (edge_data == NULL) /* Not currently cached */
return;
g_hash_table_steal (display->edge_resistance_info, screen);
/* We first need to clean out any window edges */
edges_to_be_freed = g_hash_table_new_full (g_direct_hash, g_direct_equal,
g_free, NULL);
@ -750,8 +760,7 @@ meta_display_cleanup_edges (MetaDisplay *display)
edge_data->bottom_data.timeout_id != 0)
g_source_remove (edge_data->bottom_data.timeout_id);
g_free (display->grab_edge_resistance_data);
display->grab_edge_resistance_data = NULL;
g_free (edge_data);
}
static int
@ -763,8 +772,9 @@ stupid_sort_requiring_extra_pointer_dereference (gconstpointer a,
return meta_rectangle_edge_cmp_ignore_type (*a_edge, *b_edge);
}
static void
static MetaEdgeResistanceData *
cache_edges (MetaDisplay *display,
MetaScreen *screen,
GList *window_edges,
GList *monitor_edges,
GList *screen_edges)
@ -848,9 +858,8 @@ cache_edges (MetaDisplay *display,
/*
* 2nd: Allocate the edges
*/
g_assert (display->grab_edge_resistance_data == NULL);
display->grab_edge_resistance_data = g_new0 (MetaEdgeResistanceData, 1);
edge_data = display->grab_edge_resistance_data;
edge_data = g_new0 (MetaEdgeResistanceData, 1);
edge_data->left_edges = g_array_sized_new (FALSE,
FALSE,
sizeof(MetaEdge*),
@ -917,21 +926,21 @@ cache_edges (MetaDisplay *display,
* avoided this sort by sticking them into the array with some simple
* merging of the lists).
*/
g_array_sort (display->grab_edge_resistance_data->left_edges,
g_array_sort (edge_data->left_edges,
stupid_sort_requiring_extra_pointer_dereference);
g_array_sort (display->grab_edge_resistance_data->right_edges,
g_array_sort (edge_data->right_edges,
stupid_sort_requiring_extra_pointer_dereference);
g_array_sort (display->grab_edge_resistance_data->top_edges,
g_array_sort (edge_data->top_edges,
stupid_sort_requiring_extra_pointer_dereference);
g_array_sort (display->grab_edge_resistance_data->bottom_edges,
g_array_sort (edge_data->bottom_edges,
stupid_sort_requiring_extra_pointer_dereference);
return edge_data;
}
static void
initialize_grab_edge_resistance_data (MetaDisplay *display)
initialize_grab_edge_resistance_data (MetaEdgeResistanceData *edge_data)
{
MetaEdgeResistanceData *edge_data = display->grab_edge_resistance_data;
edge_data->left_data.timeout_setup = FALSE;
edge_data->right_data.timeout_setup = FALSE;
edge_data->top_data.timeout_setup = FALSE;
@ -943,8 +952,9 @@ initialize_grab_edge_resistance_data (MetaDisplay *display)
edge_data->bottom_data.keyboard_buildup = 0;
}
static void
compute_resistance_and_snapping_edges (MetaDisplay *display)
static MetaEdgeResistanceData *
compute_resistance_and_snapping_edges (MetaDisplay *display,
MetaScreen *screen)
{
GList *stacked_windows;
GList *cur_window_iter;
@ -956,18 +966,17 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
* in the layer that we are working on
*/
GSList *rem_windows, *rem_win_stacking;
MetaEdgeResistanceData *edge_data;
g_assert (display->grab_window != NULL);
meta_topic (META_DEBUG_WINDOW_OPS,
"Computing edges to resist-movement or snap-to for %s.\n",
display->grab_window->desc);
"Computing edges to resist-movement or snap-to for screen %s.\n",
screen->screen_name);
/*
* 1st: Get the list of relevant windows, from bottom to top
*/
stacked_windows =
meta_stack_list_windows (display->grab_screen->stack,
display->grab_screen->active_workspace);
meta_stack_list_windows (screen->stack, screen->active_workspace);
/*
* 2nd: we need to separate that stacked list into a list of windows that
@ -981,7 +990,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
while (cur_window_iter != NULL)
{
MetaWindow *cur_window = cur_window_iter->data;
if (WINDOW_EDGES_RELEVANT (cur_window, display))
if (WINDOW_EDGES_RELEVANT (cur_window, display, screen))
{
MetaRectangle *new_rect;
new_rect = g_new (MetaRectangle, 1);
@ -1016,7 +1025,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
* resistance (note that dock edges are considered screen edges
* which are handled separately
*/
if (WINDOW_EDGES_RELEVANT (cur_window, display) &&
if (WINDOW_EDGES_RELEVANT (cur_window, display, screen) &&
cur_window->type != META_WINDOW_DOCK)
{
GList *new_edges;
@ -1028,7 +1037,7 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
* by other windows or DOCKS, but that's handled below).
*/
meta_rectangle_intersect (&cur_rect,
&display->grab_screen->rect,
&screen->rect,
&reduced);
new_edges = NULL;
@ -1123,32 +1132,36 @@ compute_resistance_and_snapping_edges (MetaDisplay *display)
* monitor edges in an array for quick access. Free the edges since
* they've been cached elsewhere.
*/
cache_edges (display,
edges,
display->grab_screen->active_workspace->monitor_edges,
display->grab_screen->active_workspace->screen_edges);
edge_data = cache_edges (display, screen,
edges,
screen->active_workspace->monitor_edges,
screen->active_workspace->screen_edges);
g_list_free (edges);
/*
* 6th: Initialize the resistance timeouts and buildups
*/
initialize_grab_edge_resistance_data (display);
initialize_grab_edge_resistance_data (edge_data);
return edge_data;
}
/* Note that old_[xy] and new_[xy] are with respect to inner positions of
* the window.
*/
void
meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op)
meta_window_edge_resistance_for_move (MetaWindow *window,
MetaDevice *device,
int old_x,
int old_y,
int *new_x,
int *new_y,
MetaEdgeResistanceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op)
{
MetaRectangle old_outer, proposed_outer, new_outer;
MetaGrabInfo *grab_info;
gboolean is_resize;
meta_window_get_outer_rect (window, &old_outer);
@ -1158,10 +1171,14 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
proposed_outer.y += (*new_y - old_y);
new_outer = proposed_outer;
window->display->grab_last_user_action_was_snap = snap;
grab_info = meta_display_get_grab_info (window->display, device);
g_assert (grab_info != NULL);
grab_info->grab_last_user_action_was_snap = snap;
is_resize = FALSE;
if (apply_edge_resistance_to_each_side (window->display,
window,
device,
&old_outer,
&new_outer,
timeout_func,
@ -1223,18 +1240,20 @@ meta_window_edge_resistance_for_move (MetaWindow *window,
* sizes of the inner window.
*/
void
meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op)
meta_window_edge_resistance_for_resize (MetaWindow *window,
MetaDevice *device,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
MetaEdgeResistanceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op)
{
MetaRectangle old_outer, new_outer;
int proposed_outer_width, proposed_outer_height;
MetaGrabInfo *grab_info;
gboolean is_resize;
meta_window_get_outer_rect (window, &old_outer);
@ -1246,10 +1265,14 @@ meta_window_edge_resistance_for_resize (MetaWindow *window,
proposed_outer_width,
proposed_outer_height);
window->display->grab_last_user_action_was_snap = snap;
grab_info = meta_display_get_grab_info (window->display, device);
g_assert (grab_info != NULL);
grab_info->grab_last_user_action_was_snap = snap;
is_resize = TRUE;
if (apply_edge_resistance_to_each_side (window->display,
window,
device,
&old_outer,
&new_outer,
timeout_func,

View File

@ -26,23 +26,28 @@
#include "window-private.h"
void meta_window_edge_resistance_for_move (MetaWindow *window,
int old_x,
int old_y,
int *new_x,
int *new_y,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op);
void meta_window_edge_resistance_for_resize (MetaWindow *window,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
GSourceFunc timeout_func,
gboolean snap,
gboolean is_keyboard_op);
typedef gboolean (* MetaEdgeResistanceFunc) (MetaWindow *window,
MetaDevice *device);
void meta_window_edge_resistance_for_move (MetaWindow *window,
MetaDevice *device,
int old_x,
int old_y,
int *new_x,
int *new_y,
MetaEdgeResistanceFunc func,
gboolean snap,
gboolean is_keyboard_op);
void meta_window_edge_resistance_for_resize (MetaWindow *window,
MetaDevice *device,
int old_width,
int old_height,
int *new_width,
int *new_height,
int gravity,
MetaEdgeResistanceFunc func,
gboolean snap,
gboolean is_keyboard_op);
#endif /* META_EDGE_RESISTANCE_H */

View File

@ -28,6 +28,7 @@
#include "bell.h"
#include <meta/errors.h>
#include "keybindings-private.h"
#include "device-pointer.h"
#include <X11/extensions/Xrender.h>
@ -64,7 +65,7 @@ meta_window_ensure_frame (MetaWindow *window)
frame->child_y = 0;
frame->bottom_height = 0;
frame->right_width = 0;
frame->current_cursor = 0;
frame->cursors = g_hash_table_new (NULL, NULL);
frame->mapped = FALSE;
frame->is_flashing = FALSE;
@ -228,9 +229,10 @@ meta_window_destroy_frame (MetaWindow *window)
/* Move keybindings to window instead of frame */
meta_window_grab_keys (window);
g_hash_table_destroy (frame->cursors);
g_free (frame);
/* Put our state back where it should be */
meta_window_queue (window, META_QUEUE_CALC_SHOWING);
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
@ -244,6 +246,12 @@ meta_frame_get_flags (MetaFrame *frame)
flags = 0;
/* Disallow frame operations
* while the popup menu is open.
*/
if (frame->window->menu)
return flags;
if (frame->window->border_only)
{
; /* FIXME this may disable the _function_ as well as decor
@ -382,8 +390,7 @@ meta_frame_sync_to_window (MetaFrame *frame,
/* If we're interactively resizing the frame, repaint
* it immediately so we don't start to lag.
*/
if (frame->window->display->grab_window ==
frame->window)
if (frame->window->cur_grab != NULL)
meta_ui_repaint_frame (frame->window->screen->ui,
frame->xwindow);
}
@ -408,22 +415,22 @@ meta_frame_queue_draw (MetaFrame *frame)
}
void
meta_frame_set_screen_cursor (MetaFrame *frame,
MetaCursor cursor)
meta_frame_set_screen_cursor (MetaFrame *frame,
MetaDevice *pointer,
MetaCursor cursor)
{
Cursor xcursor;
if (cursor == frame->current_cursor)
MetaCursor old_cursor;
old_cursor = GPOINTER_TO_UINT (g_hash_table_lookup (frame->cursors, pointer));
if (cursor == old_cursor)
return;
frame->current_cursor = cursor;
if (cursor == META_CURSOR_DEFAULT)
XUndefineCursor (frame->window->display->xdisplay, frame->xwindow);
else
{
xcursor = meta_display_create_x_cursor (frame->window->display, cursor);
XDefineCursor (frame->window->display->xdisplay, frame->xwindow, xcursor);
XFlush (frame->window->display->xdisplay);
XFreeCursor (frame->window->display->xdisplay, xcursor);
}
g_hash_table_insert (frame->cursors, pointer,
GUINT_TO_POINTER (cursor));
meta_device_pointer_set_window_cursor (META_DEVICE_POINTER (pointer),
frame->xwindow, cursor);
XFlush (frame->window->display->xdisplay);
}
Window

View File

@ -34,7 +34,7 @@ struct _MetaFrame
/* reparent window */
Window xwindow;
MetaCursor current_cursor;
GHashTable *cursors;
/* This rect is trusted info from where we put the
* frame, not the result of ConfigureNotify
@ -76,7 +76,8 @@ gboolean meta_frame_sync_to_window (MetaFrame *frame,
cairo_region_t *meta_frame_get_frame_bounds (MetaFrame *frame);
void meta_frame_set_screen_cursor (MetaFrame *frame,
void meta_frame_set_screen_cursor (MetaFrame *frame,
MetaDevice *pointer,
MetaCursor cursor);
#endif

677
src/core/input-events.c Normal file
View File

@ -0,0 +1,677 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/* XEvent utility methods */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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.
*/
#include <config.h>
#include "input-events.h"
#include "devices-core.h"
#include "device-map-private.h"
#include <X11/Xlib.h>
#ifdef HAVE_XINPUT2
#include <X11/extensions/XInput2.h>
#endif
/* Quite a hack: normalizes XI2 events to their
* core event equivalent, so most code is shared
* for both implementations, code handling input
* events should use the helper functions so
* the actual event is treated correctly.
*/
gboolean
meta_input_event_get_type (MetaDisplay *display,
XEvent *ev,
guint *ev_type)
{
guint type = 0; /* Silence gcc */
gboolean retval = TRUE;
#ifdef HAVE_XINPUT2
if (display->have_xinput2 &&
ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
/* NB: GDK event filters already have generic events
* allocated, so no need to do XGetEventData() on our own
*/
xev = (XIEvent *) ev->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
type = MotionNotify;
break;
case XI_ButtonPress:
type = ButtonPress;
break;
case XI_ButtonRelease:
type = ButtonRelease;
break;
case XI_KeyPress:
type = KeyPress;
break;
case XI_KeyRelease:
type = KeyRelease;
break;
case XI_FocusIn:
type = FocusIn;
break;
case XI_FocusOut:
type = FocusOut;
break;
case XI_Enter:
type = EnterNotify;
break;
case XI_Leave:
type = LeaveNotify;
break;
default:
retval = FALSE;
break;
}
}
else
#endif /* HAVE_XINPUT2 */
{
switch (ev->type)
{
case MotionNotify:
case ButtonPress:
case ButtonRelease:
case KeyPress:
case KeyRelease:
case FocusIn:
case FocusOut:
case EnterNotify:
case LeaveNotify:
type = ev->type;
break;
default:
retval = FALSE;
break;
}
}
if (retval)
{
if (ev_type)
*ev_type = type;
return TRUE;
}
else
return FALSE;
}
gboolean
meta_input_event_is_type (MetaDisplay *display,
XEvent *ev,
guint ev_type)
{
guint type;
if (!meta_input_event_get_type (display, ev, &type))
return FALSE;
return (type == ev_type);
}
Window
meta_input_event_get_window (MetaDisplay *display,
XEvent *ev)
{
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
/* GDK event filters already have generic events allocated */
xev = (XIEvent *) ev->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
return ((XIDeviceEvent *) xev)->event;
case XI_FocusIn:
case XI_FocusOut:
case XI_Enter:
case XI_Leave:
return ((XIEnterEvent *) xev)->event;
default:
return None;
}
}
else
#endif /* HAVE_XINPUT2 */
return ev->xany.window;
}
Window
meta_input_event_get_root_window (MetaDisplay *display,
XEvent *ev)
{
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
return ((XIDeviceEvent *) xev)->root;
case XI_FocusIn:
case XI_FocusOut:
case XI_Enter:
case XI_Leave:
return ((XIEnterEvent *) xev)->root;
default:
break;
}
}
else
#endif /* HAVE_XINPUT2 */
{
switch (ev->type)
{
case KeyPress:
case KeyRelease:
return ev->xkey.root;
case ButtonPress:
case ButtonRelease:
return ev->xbutton.root;
case EnterNotify:
case LeaveNotify:
return ev->xcrossing.root;
case MotionNotify:
return ev->xbutton.root;
default:
break;
}
}
return None;
}
Time
meta_input_event_get_time (MetaDisplay *display,
XEvent *ev)
{
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
return ((XIDeviceEvent *) xev)->time;
case XI_FocusIn:
case XI_FocusOut:
case XI_Enter:
case XI_Leave:
return ((XIEnterEvent *) xev)->time;
default:
break;
}
}
else
#endif /* HAVE_XINPUT2 */
{
switch (ev->type)
{
case KeyPress:
case KeyRelease:
return ev->xkey.time;
case ButtonPress:
case ButtonRelease:
return ev->xbutton.time;
case EnterNotify:
case LeaveNotify:
return ev->xcrossing.time;
case MotionNotify:
return ev->xmotion.time;
default:
break;
}
}
return CurrentTime;
}
gboolean
meta_input_event_get_coordinates (MetaDisplay *display,
XEvent *ev,
gdouble *x_ret,
gdouble *y_ret,
gdouble *x_root_ret,
gdouble *y_root_ret)
{
gdouble x, y, x_root, y_root;
gboolean retval = TRUE;
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
{
XIDeviceEvent *event = (XIDeviceEvent *) xev;
x = event->event_x;
y = event->event_y;
x_root = event->root_x;
y_root = event->root_y;
}
break;
case XI_FocusIn:
case XI_FocusOut:
case XI_Enter:
case XI_Leave:
{
XIEnterEvent *event = (XIEnterEvent *) xev;
x = event->event_x;
y = event->event_y;
x_root = event->root_x;
y_root = event->root_y;
}
break;
default:
retval = FALSE;
break;
}
}
else
#endif /* HAVE_XINPUT2 */
{
switch (ev->type)
{
case KeyPress:
case KeyRelease:
x = ev->xkey.x;
y = ev->xkey.y;
x_root = ev->xkey.x_root;
y_root = ev->xkey.y_root;
break;
case ButtonPress:
case ButtonRelease:
x = ev->xbutton.x;
y = ev->xbutton.y;
x_root = ev->xbutton.x_root;
y_root = ev->xbutton.y_root;
break;
case EnterNotify:
case LeaveNotify:
x = ev->xcrossing.x;
y = ev->xcrossing.y;
x_root = ev->xcrossing.x_root;
y_root = ev->xcrossing.y_root;
break;
case MotionNotify:
x = ev->xmotion.x;
y = ev->xmotion.y;
x_root = ev->xmotion.x_root;
y_root = ev->xmotion.y_root;
break;
default:
retval = FALSE;
break;
}
}
if (retval)
{
if (x_ret)
*x_ret = x;
if (y_ret)
*y_ret = y;
if (x_root_ret)
*x_root_ret = x_root;
if (y_root_ret)
*y_root_ret = y_root;
}
return retval;
}
gboolean
meta_input_event_get_state (MetaDisplay *display,
XEvent *ev,
guint *state)
{
gboolean retval = TRUE;
guint s;
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
switch (xev->evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
s = ((XIDeviceEvent *) xev)->mods.effective;
break;
case XI_FocusIn:
case XI_FocusOut:
case XI_Enter:
case XI_Leave:
s = ((XIDeviceEvent *) xev)->mods.effective;
break;
default:
retval = FALSE;
break;
}
}
else
#endif /* HAVE_XINPUT2 */
{
switch (ev->type)
{
case KeyPress:
case KeyRelease:
s = ev->xkey.state;
break;
case ButtonPress:
case ButtonRelease:
s = ev->xbutton.state;
break;
case EnterNotify:
case LeaveNotify:
s = ev->xcrossing.state;
break;
case MotionNotify:
s = ev->xmotion.state;
break;
default:
retval = FALSE;
break;
}
}
if (retval && state)
*state = s;
return retval;
}
gboolean
meta_input_event_get_keycode (MetaDisplay *display,
XEvent *ev,
guint *keycode)
{
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
if (xev->evtype == XI_KeyPress ||
xev->evtype == XI_KeyRelease)
{
if (keycode)
{
/* The detail field contains keycode for key events */
*keycode = ((XIDeviceEvent *) xev)->detail;
}
return TRUE;
}
}
else
#endif /* HAVE_XINPUT2 */
{
if (ev->type == KeyPress ||
ev->type == KeyRelease)
{
if (keycode)
*keycode = ev->xkey.keycode;
return TRUE;
}
}
return FALSE;
}
gboolean
meta_input_event_get_button (MetaDisplay *display,
XEvent *ev,
guint *button)
{
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
if (xev->evtype == XI_ButtonPress ||
xev->evtype == XI_ButtonRelease)
{
if (button)
{
/* The detail field contains
* button number for button events
*/
*button = ((XIDeviceEvent *) xev)->detail;
}
return TRUE;
}
}
else
#endif /* HAVE_XINPUT2 */
{
if (ev->type == ButtonPress ||
ev->type == ButtonRelease)
{
if (button)
*button = ev->xbutton.button;
return TRUE;
}
}
return FALSE;
}
/* NB: Also works for focus in/out events */
gboolean
meta_input_event_get_crossing_details (MetaDisplay *display,
XEvent *ev,
guint *mode_out,
guint *detail_out)
{
gboolean retval = TRUE;
guint mode, detail;
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
if (xev->evtype == XI_Enter ||
xev->evtype == XI_Leave ||
xev->evtype == XI_FocusIn ||
xev->evtype == XI_FocusOut)
{
mode = ((XIEnterEvent *) xev)->mode;
detail = ((XIEnterEvent *) xev)->detail;
}
else
retval = FALSE;
}
else
#endif /* HAVE_XINPUT2 */
{
if (ev->type == EnterNotify ||
ev->type == LeaveNotify)
{
mode = ev->xcrossing.mode;
detail = ev->xcrossing.detail;
}
else if (ev->type == FocusIn ||
ev->type == FocusOut)
{
mode = ev->xfocus.mode;
detail = ev->xfocus.detail;
}
else
retval = FALSE;
}
if (retval)
{
if (mode_out)
*mode_out = mode;
if (detail_out)
*detail_out = detail;
}
return retval;
}
MetaDevice *
meta_input_event_get_device (MetaDisplay *display,
XEvent *ev)
{
guint evtype;
if (!meta_input_event_get_type (display, ev, &evtype))
return NULL;
#ifdef HAVE_XINPUT2
if (ev->type == GenericEvent &&
ev->xcookie.extension == display->xinput2_opcode)
{
XIEvent *xev;
g_assert (display->have_xinput2 == TRUE);
xev = (XIEvent *) ev->xcookie.data;
switch (evtype)
{
case XI_Motion:
case XI_ButtonPress:
case XI_ButtonRelease:
case XI_KeyPress:
case XI_KeyRelease:
return meta_device_map_lookup (display->device_map,
((XIDeviceEvent *) xev)->deviceid);
case XI_FocusIn:
case XI_FocusOut:
case XI_Enter:
case XI_Leave:
return meta_device_map_lookup (display->device_map,
((XIEnterEvent *) xev)->deviceid);
default:
break;
}
}
else
#endif
{
switch (ev->type)
{
case KeyPress:
case KeyRelease:
case FocusIn:
case FocusOut:
return meta_device_map_lookup (display->device_map,
META_CORE_KEYBOARD_ID);
default:
/* All other events are pointers' */
return meta_device_map_lookup (display->device_map,
META_CORE_POINTER_ID);
}
}
return NULL;
}

78
src/core/input-events.h Normal file
View File

@ -0,0 +1,78 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/**
* \file event.h Utility functions for handling events
*
* Handling events.
* This file contains helper methods to handle events, specially
* input events, which can be either core or XInput2.
*/
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_EVENT_H
#define META_EVENT_H
#include <config.h>
#include <X11/Xlib.h>
#include "display-private.h"
#include <meta/device-map.h>
gboolean meta_input_event_get_type (MetaDisplay *display,
XEvent *ev,
guint *ev_type);
gboolean meta_input_event_is_type (MetaDisplay *display,
XEvent *ev,
guint ev_type);
Window meta_input_event_get_window (MetaDisplay *display,
XEvent *ev);
Window meta_input_event_get_root_window (MetaDisplay *display,
XEvent *ev);
Time meta_input_event_get_time (MetaDisplay *display,
XEvent *ev);
gboolean meta_input_event_get_coordinates (MetaDisplay *display,
XEvent *ev,
gdouble *x_ret,
gdouble *y_ret,
gdouble *x_root_ret,
gdouble *y_root_ret);
gboolean meta_input_event_get_state (MetaDisplay *display,
XEvent *ev,
guint *state);
gboolean meta_input_event_get_keycode (MetaDisplay *display,
XEvent *ev,
guint *keycode);
gboolean meta_input_event_get_button (MetaDisplay *display,
XEvent *event,
guint *button);
gboolean meta_input_event_get_crossing_details (MetaDisplay *display,
XEvent *ev,
guint *mode_out,
guint *detail_out);
MetaDevice *meta_input_event_get_device (MetaDisplay *display,
XEvent *ev);
#endif /* META_EVENT_H */

View File

@ -57,14 +57,18 @@ void meta_display_shutdown_keys (MetaDisplay *display);
void meta_screen_grab_keys (MetaScreen *screen);
void meta_screen_ungrab_keys (MetaScreen *screen);
gboolean meta_screen_grab_all_keys (MetaScreen *screen,
MetaDevice *device,
guint32 timestamp);
void meta_screen_ungrab_all_keys (MetaScreen *screen,
void meta_screen_ungrab_all_keys (MetaScreen *screen,
MetaDevice *device,
guint32 timestamp);
void meta_window_grab_keys (MetaWindow *window);
void meta_window_ungrab_keys (MetaWindow *window);
gboolean meta_window_grab_all_keys (MetaWindow *window,
MetaDevice *device,
guint32 timestamp);
void meta_window_ungrab_all_keys (MetaWindow *window,
MetaDevice *device,
guint32 timestamp);
gboolean meta_display_process_key_event (MetaDisplay *display,
MetaWindow *window,

File diff suppressed because it is too large Load Diff

View File

@ -301,9 +301,12 @@ static GSourceFuncs event_funcs = {
static void
meta_clutter_init (void)
{
if (!meta_get_use_core_devices ())
clutter_x11_enable_xinput ();
clutter_x11_set_display (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()));
clutter_x11_disable_event_retrieval ();
if (CLUTTER_INIT_SUCCESS == clutter_init (NULL, NULL))
{
GSource *source = g_source_new (&event_funcs, sizeof (GSource));
@ -414,6 +417,8 @@ meta_init (void)
meta_set_verbose (TRUE);
if (g_getenv ("MUTTER_DEBUG"))
meta_set_debugging (TRUE);
if (g_getenv ("MUTTER_USE_CORE_DEVICES"))
meta_set_use_core_devices (TRUE);
if (g_get_home_dir ())
if (chdir (g_get_home_dir ()) < 0)

View File

@ -69,8 +69,6 @@ main (int argc, char **argv)
GOptionContext *ctx;
GError *error = NULL;
g_type_init ();
ctx = meta_get_option_context ();
g_option_context_add_main_entries (ctx, mutter_options, GETTEXT_PACKAGE);
if (!g_option_context_parse (ctx, &argc, &argv, &error))

View File

@ -90,6 +90,7 @@ northwestcmp (gconstpointer a, gconstpointer b)
static void
find_next_cascade (MetaWindow *window,
MetaDevice *pointer,
MetaFrameBorders *borders,
/* visible windows on relevant workspaces */
GList *windows,
@ -136,7 +137,7 @@ find_next_cascade (MetaWindow *window,
* of NW corner of window frame.
*/
current = meta_screen_get_current_monitor (window->screen);
current = meta_screen_get_current_monitor (window->screen, pointer);
meta_window_get_work_area_for_monitor (window, current, &work_area);
cascade_x = MAX (0, work_area.x);
@ -354,10 +355,17 @@ avoid_being_obscured_as_second_modal_dialog (MetaWindow *window,
* know about the modal-to-the-main-window part.
*/
MetaWindow *focus_window;
MetaWindow *focus_window = NULL;
MetaFocusInfo *focus_info;
MetaRectangle overlap;
MetaDevice *pointer, *keyboard;
focus_window = window->display->focus_window;
pointer = meta_window_guess_grab_pointer (window);
keyboard = meta_device_get_paired_device (pointer);
focus_info = meta_display_get_focus_info (window->display, keyboard);
if (focus_window)
focus_window = focus_info->focus_window;
if (window->denied_focus_and_not_transient &&
window->wm_state_modal && /* FIXME: Maybe do this for all transients? */
@ -660,6 +668,7 @@ meta_window_place (MetaWindow *window,
{
GList *windows;
const MetaMonitorInfo *xi;
MetaDevice *pointer, *keyboard;
/* frame member variables should NEVER be used in here, only
* MetaFrameBorders. But remember borders == NULL
@ -671,7 +680,9 @@ meta_window_place (MetaWindow *window,
meta_topic (META_DEBUG_PLACEMENT, "Placing window %s\n", window->desc);
windows = NULL;
pointer = meta_window_guess_grab_pointer (window);
keyboard = meta_device_get_paired_device (pointer);
switch (window->type)
{
/* Run placement algorithm on these. */
@ -815,7 +826,7 @@ meta_window_place (MetaWindow *window,
int w, h;
/* Warning, this function is a round trip! */
xi = meta_screen_get_current_monitor_info (window->screen);
xi = meta_screen_get_current_monitor_info (window->screen, pointer);
w = xi->rect.width;
h = xi->rect.height;
@ -860,8 +871,8 @@ meta_window_place (MetaWindow *window,
}
/* Warning, this is a round trip! */
xi = meta_screen_get_current_monitor_info (window->screen);
xi = meta_screen_get_current_monitor_info (window->screen, pointer);
/* "Origin" placement algorithm */
x = xi->rect.x;
y = xi->rect.y;
@ -899,8 +910,8 @@ meta_window_place (MetaWindow *window,
/* If no placement has been done, revert to cascade to avoid
* fully overlapping window (e.g. starting multiple terminals)
* */
if (x == xi->rect.x && y == xi->rect.y)
find_next_cascade (window, borders, windows, x, y, &x, &y);
if (x == xi->rect.x && y == xi->rect.y)
find_next_cascade (window, pointer, borders, windows, x, y, &x, &y);
done_check_denied_focus:
/* If the window is being denied focus and isn't a transient of the
@ -913,8 +924,12 @@ meta_window_place (MetaWindow *window,
gboolean found_fit;
MetaWindow *focus_window;
MetaRectangle overlap;
MetaFocusInfo *focus_info;
focus_window = window->display->focus_window;
focus_info = meta_display_get_focus_info (window->display, keyboard);
g_assert (focus_info != NULL);
focus_window = focus_info->focus_window;
g_assert (focus_window != NULL);
/* No need to do anything if the window doesn't overlap at all */

View File

@ -92,7 +92,8 @@ struct _MetaScreen
MetaStack *stack;
MetaStackTracker *stack_tracker;
MetaCursor current_cursor;
/* per-pointer cursors */
GHashTable *cursors;
Window flash_window;
@ -158,8 +159,10 @@ void meta_screen_foreach_window (MetaScreen *scree
gpointer data);
void meta_screen_set_cursor (MetaScreen *screen,
MetaDevice *pointer,
MetaCursor cursor);
void meta_screen_update_cursor (MetaScreen *screen);
void meta_screen_update_cursor (MetaScreen *screen,
MetaDevice *pointer);
void meta_screen_tab_popup_create (MetaScreen *screen,
MetaTabList list_type,
@ -182,9 +185,11 @@ void meta_screen_tile_preview_update (MetaScreen *screen,
void meta_screen_tile_preview_hide (MetaScreen *screen);
MetaWindow* meta_screen_get_mouse_window (MetaScreen *screen,
MetaDevice *pointer,
MetaWindow *not_this_one);
const MetaMonitorInfo* meta_screen_get_current_monitor_info (MetaScreen *screen);
const MetaMonitorInfo* meta_screen_get_current_monitor_info (MetaScreen *screen,
MetaDevice *pointer);
const MetaMonitorInfo* meta_screen_get_monitor_for_rect (MetaScreen *screen,
MetaRectangle *rect);
const MetaMonitorInfo* meta_screen_get_monitor_for_window (MetaScreen *screen,

View File

@ -37,9 +37,11 @@
#include "workspace-private.h"
#include "keybindings-private.h"
#include "stack.h"
#include "core.h"
#include "xprops.h"
#include <meta/compositor.h>
#include "mutter-enum-types.h"
#include "device-pointer.h"
#include <X11/extensions/Xinerama.h>
@ -621,7 +623,6 @@ meta_screen_new (MetaDisplay *display,
MetaScreen *screen;
Window xroot;
Display *xdisplay;
XWindowAttributes attr;
Window new_wm_sn_owner;
Window current_wm_sn_owner;
gboolean replace_current_wm;
@ -736,15 +737,15 @@ meta_screen_new (MetaDisplay *display,
/* We need to or with the existing event mask since
* gtk+ may be interested in other events.
*/
XGetWindowAttributes (xdisplay, xroot, &attr);
XSelectInput (xdisplay,
xroot,
SubstructureRedirectMask | SubstructureNotifyMask |
ColormapChangeMask | PropertyChangeMask |
LeaveWindowMask | EnterWindowMask |
KeyPressMask | KeyReleaseMask |
FocusChangeMask | StructureNotifyMask |
ExposureMask | attr.your_event_mask);
meta_core_select_events (xdisplay, xroot,
(SubstructureRedirectMask | SubstructureNotifyMask |
ColormapChangeMask | PropertyChangeMask |
LeaveWindowMask | EnterWindowMask |
KeyPressMask | KeyReleaseMask |
FocusChangeMask | StructureNotifyMask |
ExposureMask),
TRUE);
if (meta_error_trap_pop_with_return (display) != Success)
{
meta_warning (_("Screen %d on display \"%s\" already has a window manager\n"),
@ -766,10 +767,10 @@ meta_screen_new (MetaDisplay *display,
screen->rect.x = screen->rect.y = 0;
screen->rect.width = WidthOfScreen (screen->xscreen);
screen->rect.height = HeightOfScreen (screen->xscreen);
screen->current_cursor = -1; /* invalid/unset */
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
screen->flash_window = None;
screen->cursors = g_hash_table_new (NULL, NULL);
screen->wm_sn_selection_window = new_wm_sn_owner;
screen->wm_sn_atom = wm_sn_atom;
@ -794,8 +795,6 @@ meta_screen_new (MetaDisplay *display,
screen->last_monitor_index = 0;
reload_monitor_infos (screen);
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
/* Handle creating a no_focus_window for this screen */
screen->no_focus_window =
@ -930,7 +929,10 @@ meta_screen_free (MetaScreen *screen,
meta_stack_tracker_free (screen->stack_tracker);
meta_error_trap_push_with_return (screen->display);
XSelectInput (screen->display->xdisplay, screen->xroot, 0);
meta_core_select_events (screen->display->xdisplay,
screen->xroot, NoEventMask,
FALSE);
if (meta_error_trap_pop_with_return (screen->display) != Success)
meta_warning (_("Could not release screen %d on display \"%s\"\n"),
screen->number, screen->display->name);
@ -954,6 +956,8 @@ meta_screen_free (MetaScreen *screen,
g_free (screen->screen_name);
g_hash_table_destroy (screen->cursors);
g_object_unref (screen);
XFlush (display->xdisplay);
@ -1464,7 +1468,30 @@ update_num_workspaces (MetaScreen *screen,
MetaWorkspace *last_remaining;
gboolean need_change_space;
new_num = meta_prefs_get_num_workspaces ();
if (meta_prefs_get_dynamic_workspaces ())
{
int n_items;
gulong *list;
n_items = 0;
list = NULL;
if (meta_prop_get_cardinal_list (screen->display, screen->xroot,
screen->display->atom__NET_NUMBER_OF_DESKTOPS,
&list, &n_items))
{
new_num = list[0];
meta_XFree (list);
}
else
{
new_num = 1;
}
}
else
{
new_num = meta_prefs_get_num_workspaces ();
}
g_assert (new_num > 0);
@ -1549,31 +1576,33 @@ update_focus_mode (MetaScreen *screen)
void
meta_screen_set_cursor (MetaScreen *screen,
MetaDevice *pointer,
MetaCursor cursor)
{
Cursor xcursor;
MetaCursor old_cursor;
if (cursor == screen->current_cursor)
old_cursor = GPOINTER_TO_UINT (g_hash_table_lookup (screen->cursors, pointer));
if (cursor == old_cursor)
return;
screen->current_cursor = cursor;
xcursor = meta_display_create_x_cursor (screen->display, cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
g_hash_table_insert (screen->cursors, pointer,
GUINT_TO_POINTER (cursor));
meta_screen_update_cursor (screen, pointer);
}
void
meta_screen_update_cursor (MetaScreen *screen)
meta_screen_update_cursor (MetaScreen *screen,
MetaDevice *pointer)
{
Cursor xcursor;
MetaCursor cursor;
xcursor = meta_display_create_x_cursor (screen->display,
screen->current_cursor);
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
cursor = GPOINTER_TO_UINT (g_hash_table_lookup (screen->cursors, pointer));
meta_device_pointer_set_window_cursor (META_DEVICE_POINTER (pointer),
screen->xroot,
cursor);
XFlush (screen->display->xdisplay);
XFreeCursor (screen->display->xdisplay, xcursor);
}
void
@ -1827,8 +1856,20 @@ static gboolean
meta_screen_tile_preview_update_timeout (gpointer data)
{
MetaScreen *screen = data;
MetaWindow *window = screen->display->grab_window;
MetaWindow *window = NULL;
gboolean needs_preview = FALSE;
MetaGrabInfo *grab_info;
MetaDevice *pointer = NULL;
GHashTableIter iter;
/* FIXME: we're just handling the first grab we find */
g_hash_table_iter_init (&iter, screen->display->current_grabs);
if (g_hash_table_iter_next (&iter, NULL, (gpointer *) &grab_info))
{
window = grab_info->grab_window;
pointer = grab_info->grab_pointer;
}
screen->tile_preview_timeout_id = 0;
@ -1871,7 +1912,7 @@ meta_screen_tile_preview_update_timeout (gpointer data)
MetaRectangle tile_rect;
meta_window_get_current_tile_area (window, &tile_rect);
meta_tile_preview_show (screen->tile_preview, &tile_rect);
meta_tile_preview_show (screen->tile_preview, pointer, &tile_rect);
}
else
meta_tile_preview_hide (screen->tile_preview);
@ -1916,28 +1957,23 @@ meta_screen_tile_preview_hide (MetaScreen *screen)
MetaWindow*
meta_screen_get_mouse_window (MetaScreen *screen,
MetaDevice *pointer,
MetaWindow *not_this_one)
{
MetaWindow *window;
Window root_return, child_return;
int root_x_return, root_y_return;
int win_x_return, win_y_return;
unsigned int mask_return;
if (not_this_one)
meta_topic (META_DEBUG_FOCUS,
"Focusing mouse window excluding %s\n", not_this_one->desc);
meta_error_trap_push (screen->display);
XQueryPointer (screen->display->xdisplay,
screen->xroot,
&root_return,
&child_return,
&root_x_return,
&root_y_return,
&win_x_return,
&win_y_return,
&mask_return);
meta_device_pointer_query_position (META_DEVICE_POINTER (pointer),
screen->xroot,
NULL, NULL,
&root_x_return,
&root_y_return,
NULL, NULL, NULL);
meta_error_trap_pop (screen->display);
window = meta_stack_get_default_focus_window_at_point (screen->stack,
@ -2033,6 +2069,7 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
const MetaMonitorInfo* current;
const MetaMonitorInfo* tmp;
GQueue* monitor_queue;
MetaDevice *pointer;
int* visited;
int cur = 0;
int i;
@ -2040,6 +2077,9 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
*n_monitors = screen->n_monitor_infos;
*monitors_list = g_new (int, screen->n_monitor_infos);
pointer = meta_device_map_lookup (screen->display->device_map,
META_CORE_POINTER_ID);
/* we calculate a natural ordering by which to choose monitors for
* window placement. We start at the current monitor, and perform
* a breadth-first search of the monitors starting from that
@ -2054,7 +2094,7 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
visited[i] = FALSE;
}
current = meta_screen_get_current_monitor_info (screen);
current = meta_screen_get_current_monitor_info (screen, pointer);
monitor_queue = g_queue_new ();
g_queue_push_tail (monitor_queue, (gpointer) current);
visited[current->number] = TRUE;
@ -2121,11 +2161,12 @@ meta_screen_get_natural_monitor_list (MetaScreen *screen,
}
const MetaMonitorInfo*
meta_screen_get_current_monitor_info (MetaScreen *screen)
meta_screen_get_current_monitor_info (MetaScreen *screen,
MetaDevice *pointer)
{
int monitor_index;
monitor_index = meta_screen_get_current_monitor (screen);
return &screen->monitor_infos[monitor_index];
int monitor_index;
monitor_index = meta_screen_get_current_monitor (screen, pointer);
return &screen->monitor_infos[monitor_index];
}
/**
@ -2137,7 +2178,8 @@ meta_screen_get_current_monitor_info (MetaScreen *screen)
* Return value: a monitor index
*/
int
meta_screen_get_current_monitor (MetaScreen *screen)
meta_screen_get_current_monitor (MetaScreen *screen,
MetaDevice *pointer)
{
if (screen->n_monitor_infos == 1)
return 0;
@ -2147,24 +2189,18 @@ meta_screen_get_current_monitor (MetaScreen *screen)
if (screen->display->monitor_cache_invalidated)
{
Window root_return, child_return;
int win_x_return, win_y_return;
unsigned int mask_return;
int i;
MetaRectangle pointer_position;
screen->display->monitor_cache_invalidated = FALSE;
pointer_position.width = pointer_position.height = 1;
XQueryPointer (screen->display->xdisplay,
screen->xroot,
&root_return,
&child_return,
&pointer_position.x,
&pointer_position.y,
&win_x_return,
&win_y_return,
&mask_return);
meta_device_pointer_query_position (META_DEVICE_POINTER (pointer),
screen->xroot,
NULL, NULL,
&pointer_position.x,
&pointer_position.y,
NULL, NULL, NULL);
screen->last_monitor_index = 0;
for (i = 0; i < screen->n_monitor_infos; i++)
@ -3037,17 +3073,22 @@ static gboolean startup_sequence_timeout (void *data);
static void
update_startup_feedback (MetaScreen *screen)
{
MetaDevice *pointer;
pointer = meta_device_map_lookup (screen->display->device_map,
META_CORE_POINTER_ID);
if (screen->startup_sequences != NULL)
{
meta_topic (META_DEBUG_STARTUP,
"Setting busy cursor\n");
meta_screen_set_cursor (screen, META_CURSOR_BUSY);
meta_screen_set_cursor (screen, pointer, META_CURSOR_BUSY);
}
else
{
meta_topic (META_DEBUG_STARTUP,
"Setting default cursor\n");
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
meta_screen_set_cursor (screen, pointer, META_CURSOR_DEFAULT);
}
}

View File

@ -274,13 +274,23 @@ meta_stack_update_window_tile_matches (MetaStack *stack,
g_list_free (windows);
}
typedef struct _FocusedForeachData FocusedForeachData;
struct _FocusedForeachData
{
MetaWindow *window;
gboolean focused_transient;
};
static gboolean
is_focused_foreach (MetaWindow *window,
void *data)
{
if (window == window->display->expected_focus_window)
FocusedForeachData *focused_data = data;
if (window == focused_data->window)
{
*((gboolean*) data) = TRUE;
focused_data->focused_transient = TRUE;
return FALSE;
}
return TRUE;
@ -303,6 +313,9 @@ get_standalone_layer (MetaWindow *window)
{
MetaStackLayer layer;
gboolean focused_transient = FALSE;
MetaFocusInfo *focus_info;
MetaDevice *keyboard;
FocusedForeachData focused_data = { 0 };
switch (window->type)
{
@ -326,20 +339,30 @@ get_standalone_layer (MetaWindow *window)
case META_WINDOW_OVERRIDE_OTHER:
layer = META_LAYER_OVERRIDE_REDIRECT;
break;
default:
default:
/* FIXME: How about other keyboards? should
* we allow fullscreen for non-VCP/K anyway?
*/
keyboard = meta_device_map_lookup (window->display->device_map,
META_CORE_KEYBOARD_ID);
focus_info = meta_display_get_focus_info (window->display, keyboard);
focused_data.window = focus_info->expected_focus_window;
meta_window_foreach_transient (window,
is_focused_foreach,
&focused_transient);
&focused_data);
if (window->wm_state_below)
layer = META_LAYER_BOTTOM;
else if (window->fullscreen &&
(focused_transient ||
window == window->display->expected_focus_window ||
window->display->expected_focus_window == NULL ||
(window->display->expected_focus_window != NULL &&
!focus_info ||
window == focus_info->expected_focus_window ||
focus_info->expected_focus_window == NULL ||
(focus_info->expected_focus_window != NULL &&
windows_on_different_monitor (window,
window->display->expected_focus_window))))
focus_info->expected_focus_window))))
layer = META_LAYER_FULLSCREEN;
else if (window->wm_state_above && !META_WINDOW_MAXIMIZED (window))
layer = META_LAYER_TOP;

View File

@ -50,6 +50,7 @@ meta_topic_real_valist (MetaDebugTopic topic,
static gint verbose_topics = 0;
static gboolean is_debugging = FALSE;
static gboolean replace_current = FALSE;
static gboolean use_core_devices = FALSE;
static int no_prefix = 0;
#ifdef WITH_VERBOSE_MODE
@ -178,6 +179,18 @@ meta_set_debugging (gboolean setting)
is_debugging = setting;
}
gboolean
meta_get_use_core_devices (void)
{
return use_core_devices;
}
void
meta_set_use_core_devices (gboolean setting)
{
use_core_devices = setting;
}
gboolean
meta_get_replace_current_wm (void)
{

View File

@ -115,6 +115,10 @@ struct _MetaWindow
Window xgroup_leader;
Window xclient_leader;
/* window menu if any, and the pointer that popped it up */
MetaWindowMenu *menu;
MetaDevice *menu_device;
/* Initial workspace property */
int initial_workspace;
@ -333,6 +337,12 @@ struct _MetaWindow
/* if TRUE, window is attached to its parent */
guint attached : 1;
/* if TRUE, window didn't yet get the FocusIn for window->focus_keyboard */
guint expecting_focus_in : 1;
/* Keyboard currently owning the window focus, or NULL */
MetaDevice *focus_keyboard;
/* if non-NULL, the bounds of the window frame */
cairo_region_t *frame_bounds;
@ -413,6 +423,12 @@ struct _MetaWindow
/* The currently complementary tiled window, if any */
MetaWindow *tile_match;
/* Current grab op for this window, or NULL */
MetaGrabInfo *cur_grab;
/* Focus info if the window is focused, or NULL */
MetaFocusInfo *cur_focus;
};
struct _MetaWindowClass
@ -569,6 +585,7 @@ void meta_window_set_current_workspace_hint (MetaWindow *window);
unsigned long meta_window_get_net_wm_desktop (MetaWindow *window);
void meta_window_show_menu (MetaWindow *window,
MetaDevice *device,
int root_x,
int root_y,
int button,
@ -618,8 +635,10 @@ void meta_window_free_delete_dialog (MetaWindow *window);
void meta_window_update_keyboard_resize (MetaWindow *window,
MetaDevice *device,
gboolean update_cursor);
void meta_window_update_keyboard_move (MetaWindow *window);
void meta_window_update_keyboard_move (MetaWindow *window,
MetaDevice *device);
void meta_window_update_layer (MetaWindow *window);
@ -641,11 +660,19 @@ void meta_window_update_for_monitors_changed (MetaWindow *window);
void meta_window_update_on_all_workspaces (MetaWindow *window);
void meta_window_propagate_focus_appearance (MetaWindow *window,
MetaDevice *keyboard,
gboolean focused);
gboolean meta_window_should_attach_to_parent (MetaWindow *window);
gboolean meta_window_can_tile_side_by_side (MetaWindow *window);
gboolean meta_window_can_tile_side_by_side (MetaWindow *window,
MetaDevice *pointer);
void meta_window_compute_tile_match (MetaWindow *window);
void meta_window_set_client_pointer (MetaWindow *window,
MetaDevice *pointer);
MetaDevice * meta_window_get_client_pointer (MetaWindow *window);
MetaDevice * meta_window_guess_grab_pointer (MetaWindow *window);
#endif

View File

@ -1438,6 +1438,13 @@ reload_transient_for (MetaWindow *window,
MetaWindow *parent = NULL;
Window transient_for, old_transient_for;
if (meta_window_appears_focused (window) && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window,
window->focus_keyboard,
FALSE);
window->xtransient_for = None;
if (value->type != META_PROP_VALUE_INVALID)
{
transient_for = value->v.xwindow;
@ -1474,7 +1481,9 @@ reload_transient_for (MetaWindow *window,
return;
if (meta_window_appears_focused (window) && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, FALSE);
meta_window_propagate_focus_appearance (window,
window->focus_keyboard,
FALSE);
old_transient_for = window->xtransient_for;
window->xtransient_for = transient_for;
@ -1527,7 +1536,9 @@ reload_transient_for (MetaWindow *window,
meta_window_queue (window, META_QUEUE_MOVE_RESIZE);
if (meta_window_appears_focused (window) && window->xtransient_for != None)
meta_window_propagate_focus_appearance (window, TRUE);
meta_window_propagate_focus_appearance (window,
window->focus_keyboard,
TRUE);
}
static void

File diff suppressed because it is too large Load Diff

View File

@ -95,6 +95,7 @@ GList* meta_workspace_get_onmonitor_region (MetaWorkspace *workspace,
int which_monitor);
void meta_workspace_focus_default_window (MetaWorkspace *workspace,
MetaDevice *pointer,
MetaWindow *not_this_one,
guint32 timestamp);

View File

@ -538,7 +538,9 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
MetaWorkspaceLayout layout1, layout2;
gint num_workspaces, current_space, new_space;
MetaMotionDirection direction;
MetaGrabInfo *grab_info;
GHashTableIter iter;
meta_verbose ("Activating workspace %d\n",
meta_workspace_index (workspace));
@ -547,7 +549,7 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
/* Free any cached pointers to the workspaces's edges from
* a current resize or move operation */
meta_display_cleanup_edges (workspace->screen->display);
meta_display_cleanup_edges (workspace->screen->display, workspace->screen);
if (workspace->screen->active_workspace)
workspace_switch_sound (workspace->screen->active_workspace, workspace);
@ -570,10 +572,22 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
return;
move_window = NULL;
if (workspace->screen->display->grab_op == META_GRAB_OP_MOVING ||
workspace->screen->display->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
move_window = workspace->screen->display->grab_window;
/* FIXME: not quite multidevice friendly, but the whole
* "move window to another workspace" isn't.
*/
g_hash_table_iter_init (&iter, workspace->screen->display->current_grabs);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &grab_info))
{
if (grab_info->grab_op == META_GRAB_OP_MOVING ||
grab_info->grab_op == META_GRAB_OP_KEYBOARD_MOVING)
{
move_window = grab_info->grab_window;
break;
}
}
if (move_window != NULL)
{
if (move_window->on_all_workspaces)
@ -673,8 +687,13 @@ meta_workspace_activate_with_focus (MetaWorkspace *workspace,
}
else
{
MetaDevice *pointer;
pointer = meta_device_map_lookup (screen->display->device_map,
META_CORE_POINTER_ID);
meta_topic (META_DEBUG_FOCUS, "Focusing default window on new workspace\n");
meta_workspace_focus_default_window (workspace, NULL, timestamp);
meta_workspace_focus_default_window (workspace, pointer,
NULL, timestamp);
}
/* Emit switched signal from screen.c */
@ -774,7 +793,7 @@ meta_workspace_invalidate_work_area (MetaWorkspace *workspace)
/* If we are in the middle of a resize or move operation, we
* might have cached pointers to the workspace's edges */
if (workspace == workspace->screen->active_workspace)
meta_display_cleanup_edges (workspace->screen->display);
meta_display_cleanup_edges (workspace->screen->display, workspace->screen);
g_free (workspace->work_area_monitor);
workspace->work_area_monitor = NULL;
@ -1198,6 +1217,7 @@ meta_workspace_get_name (MetaWorkspace *workspace)
void
meta_workspace_focus_default_window (MetaWorkspace *workspace,
MetaDevice *pointer,
MetaWindow *not_this_one,
guint32 timestamp)
{
@ -1214,7 +1234,8 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace,
else
{
MetaWindow * window;
window = meta_screen_get_mouse_window (workspace->screen, not_this_one);
window = meta_screen_get_mouse_window (workspace->screen,
pointer, not_this_one);
if (window &&
window->type != META_WINDOW_DOCK &&
window->type != META_WINDOW_DESKTOP)

46
src/meta/device-map.h Normal file
View File

@ -0,0 +1,46 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_MAP_H
#define META_DEVICE_MAP_H
#include <glib-object.h>
#include <meta/types.h>
#include <meta/device.h>
#define META_TYPE_DEVICE_MAP (meta_device_map_get_type ())
#define META_DEVICE_MAP(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE_MAP, MetaDeviceMap))
#define META_DEVICE_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE_MAP, MetaDeviceMapClass))
#define META_IS_DEVICE_MAP(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE_MAP))
#define META_IS_DEVICE_MAP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE_MAP))
#define META_DEVICE_MAP_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE_MAP, MetaDeviceMapClass))
typedef struct _MetaDeviceMapClass MetaDeviceMapClass;
GType meta_device_map_get_type (void) G_GNUC_CONST;
MetaDevice * meta_device_map_lookup (MetaDeviceMap *device_map,
gint device_id);
MetaDisplay * meta_device_map_get_display (MetaDeviceMap *device_map);
GList * meta_device_map_list_devices (MetaDeviceMap *device_map);
#endif

44
src/meta/device.h Normal file
View File

@ -0,0 +1,44 @@
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
/*
* Copyright (C) 2011 Carlos Garnacho
*
* 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_DEVICE_H
#define META_DEVICE_H
#include <glib-object.h>
#include <meta/types.h>
#define META_TYPE_DEVICE (meta_device_get_type ())
#define META_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), META_TYPE_DEVICE, MetaDevice))
#define META_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), META_TYPE_DEVICE, MetaDeviceClass))
#define META_IS_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), META_TYPE_DEVICE))
#define META_IS_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), META_TYPE_DEVICE))
#define META_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), META_TYPE_DEVICE, MetaDeviceClass))
typedef struct _MetaDeviceClass MetaDeviceClass;
GType meta_device_get_type (void) G_GNUC_CONST;
int meta_device_get_id (MetaDevice *device);
MetaDisplay *meta_device_get_display (MetaDevice *device);
MetaDevice * meta_device_get_paired_device (MetaDevice *device);
#endif

View File

@ -28,6 +28,7 @@
#include <meta/types.h>
#include <meta/prefs.h>
#include <meta/common.h>
#include <meta/device-map.h>
typedef enum
{
@ -75,6 +76,9 @@ gboolean meta_display_has_shape (MetaDisplay *display);
MetaScreen *meta_display_screen_for_root (MetaDisplay *display,
Window xroot);
MetaWindow *meta_display_get_keyboard_focus_window (MetaDisplay *display,
MetaDevice *keyboard);
MetaWindow *meta_display_get_focus_window (MetaDisplay *display);
gboolean meta_display_xwindow_is_a_no_focus_window (MetaDisplay *display,
@ -111,9 +115,30 @@ MetaWindow* meta_display_get_tab_current (MetaDisplay *display,
MetaScreen *screen,
MetaWorkspace *workspace);
GList* meta_display_get_device_tab_list (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
MetaDevice *device);
MetaWindow* meta_display_get_device_tab_next (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
MetaWindow *window,
MetaDevice *device,
gboolean backward);
MetaWindow* meta_display_get_device_tab_current (MetaDisplay *display,
MetaTabList type,
MetaScreen *screen,
MetaWorkspace *workspace,
MetaDevice *device);
gboolean meta_display_begin_grab_op (MetaDisplay *display,
MetaScreen *screen,
MetaWindow *window,
MetaDevice *device,
MetaGrabOp op,
gboolean pointer_already_grabbed,
gboolean frame_action,
@ -123,6 +148,7 @@ gboolean meta_display_begin_grab_op (MetaDisplay *display,
int root_x,
int root_y);
void meta_display_end_grab_op (MetaDisplay *display,
MetaDevice *device,
guint32 timestamp);
MetaGrabOp meta_display_get_grab_op (MetaDisplay *display);
@ -137,10 +163,23 @@ gboolean meta_display_add_keybinding (MetaDisplay *display,
gboolean meta_display_remove_keybinding (MetaDisplay *display,
const char *name);
MetaGrabOp meta_display_get_device_grab_op (MetaDisplay *display,
MetaDevice *device);
MetaKeyBindingAction meta_display_get_keybinding_action (MetaDisplay *display,
unsigned int keycode,
unsigned long mask);
void meta_display_set_keyboard_focus (MetaDisplay *display,
MetaWindow *window,
MetaDevice *keyboard,
gboolean focus_frame,
guint32 timestamp);
void meta_display_unset_keyboard_focus (MetaDisplay *display,
MetaScreen *screen,
MetaDevice *keyboard,
guint32 timestamp);
/* meta_display_set_input_focus_window is like XSetInputFocus, except
* that (a) it can't detect timestamps later than the current time,
* since Mutter isn't part of the XServer, and thus gives erroneous
@ -176,5 +215,6 @@ void meta_display_unmanage_screen (MetaDisplay *display,
guint32 timestamp);
void meta_display_clear_mouse_mode (MetaDisplay *display);
MetaDeviceMap * meta_display_get_device_map (MetaDisplay *display);
#endif

View File

@ -41,6 +41,10 @@ void meta_keybindings_switch_window (MetaDisplay *display,
MetaKeyBinding *binding);
void meta_screen_ungrab_all_keys (MetaScreen *screen, guint32 timestamp);
gboolean meta_screen_grab_all_keys (MetaScreen *screen, guint32 timestamp);
void meta_screen_ungrab_all_keys (MetaScreen *screen,
MetaDevice *device,
guint32 timestamp);
gboolean meta_screen_grab_all_keys (MetaScreen *screen,
MetaDevice *device,
guint32 timestamp);
#endif

View File

@ -77,7 +77,8 @@ MetaWorkspace * meta_screen_get_active_workspace (MetaScreen *screen);
int meta_screen_get_n_monitors (MetaScreen *screen);
int meta_screen_get_primary_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor (MetaScreen *screen);
int meta_screen_get_current_monitor (MetaScreen *screen,
MetaDevice *pointer);
void meta_screen_get_monitor_geometry (MetaScreen *screen,
int monitor,
MetaRectangle *geometry);

View File

@ -32,6 +32,8 @@ typedef struct _MetaFrame MetaFrame;
typedef struct _MetaScreen MetaScreen;
typedef struct _MetaWindow MetaWindow;
typedef struct _MetaWorkspace MetaWorkspace;
typedef struct _MetaDevice MetaDevice;
typedef struct _MetaDeviceMap MetaDeviceMap;
/**
* MetaGroup: (skip)
*

View File

@ -38,6 +38,9 @@ gboolean meta_is_syncing (void);
void meta_set_syncing (gboolean setting);
void meta_set_replace_current_wm (gboolean setting);
gboolean meta_get_use_core_devices (void);
void meta_set_use_core_devices (gboolean setting);
void meta_debug_spew_real (const char *format,
...) G_GNUC_PRINTF (1, 2);
void meta_verbose_real (const char *format,

View File

@ -189,6 +189,7 @@ void meta_window_focus (MetaWindow *window,
guint32 timestamp);
void meta_window_begin_grab_op (MetaWindow *window,
MetaDevice *device,
MetaGrabOp op,
gboolean frame_action,
guint32 timestamp);

View File

@ -51,6 +51,7 @@ static void meta_frames_unmap (GtkWidget *widget);
static void meta_frames_update_prelit_control (MetaFrames *frames,
MetaUIFrame *frame,
GdkDevice *device,
MetaFrameControl control);
static gboolean meta_frames_button_press_event (GtkWidget *widget,
GdkEventButton *event);
@ -637,10 +638,12 @@ meta_frames_unmanage_window (MetaFrames *frames,
if (frame)
{
#if 0
/* restore the cursor */
meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
frame->xwindow,
META_CURSOR_DEFAULT);
#endif
gdk_window_set_user_data (frame->window, NULL);
@ -1046,10 +1049,12 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
int action)
{
MetaFrameFlags flags;
GdkDevice *pointer;
Display *display;
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
pointer = gdk_event_get_device ((GdkEvent *) event);
switch (action)
{
case G_DESKTOP_TITLEBAR_ACTION_TOGGLE_SHADE:
@ -1131,12 +1136,14 @@ meta_frame_titlebar_event (MetaUIFrame *frame,
case G_DESKTOP_TITLEBAR_ACTION_LOWER:
meta_core_user_lower_and_unfocus (display,
frame->xwindow,
gdk_x11_device_get_id (pointer),
event->time);
break;
case G_DESKTOP_TITLEBAR_ACTION_MENU:
meta_core_show_window_menu (display,
frame->xwindow,
gdk_x11_device_get_id (pointer),
event->x_root,
event->y_root,
event->button,
@ -1182,7 +1189,9 @@ meta_frames_button_press_event (GtkWidget *widget,
MetaFrames *frames;
MetaFrameControl control;
Display *display;
GdkDevice *device;
int device_id;
frames = META_FRAMES (widget);
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
@ -1213,7 +1222,10 @@ meta_frames_button_press_event (GtkWidget *widget,
/* don't do the rest of this if on client area */
if (control == META_FRAME_CONTROL_CLIENT_AREA)
return FALSE; /* not on the frame, just passed through from client */
device = gdk_event_get_device ((GdkEvent *) event);
device_id = gdk_x11_device_get_id (device);
/* We want to shade even if we have a GrabOp, since we'll have a move grab
* if we double click the titlebar.
*/
@ -1221,13 +1233,13 @@ meta_frames_button_press_event (GtkWidget *widget,
event->button == 1 &&
event->type == GDK_2BUTTON_PRESS)
{
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
return meta_frame_double_click_event (frame, event);
}
if (meta_core_get_grab_op (display) !=
if (meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL) !=
META_GRAB_OP_NONE)
return FALSE; /* already up to something */
return FALSE; /* already up to something */
if (event->button == 1 &&
(control == META_FRAME_CONTROL_MAXIMIZE ||
@ -1286,6 +1298,7 @@ meta_frames_button_press_event (GtkWidget *widget,
meta_core_begin_grab_op (display,
frame->xwindow,
device_id,
op,
TRUE,
TRUE,
@ -1318,6 +1331,7 @@ meta_frames_button_press_event (GtkWidget *widget,
meta_core_show_window_menu (display,
frame->xwindow,
device_id,
rect->x + dx,
rect->y + rect->height + dy,
event->button,
@ -1371,6 +1385,7 @@ meta_frames_button_press_event (GtkWidget *widget,
meta_core_begin_grab_op (display,
frame->xwindow,
device_id,
op,
TRUE,
TRUE,
@ -1393,6 +1408,7 @@ meta_frames_button_press_event (GtkWidget *widget,
{
meta_core_begin_grab_op (display,
frame->xwindow,
device_id,
META_GRAB_OP_MOVING,
TRUE,
TRUE,
@ -1416,28 +1432,28 @@ meta_frames_button_press_event (GtkWidget *widget,
}
void
meta_frames_notify_menu_hide (MetaFrames *frames)
meta_frames_notify_menu_hide (MetaFrames *frames,
Window client_xwindow)
{
Display *display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
if (meta_core_get_grab_op (display) ==
Window frame_xwindow;
int device_id;
frame_xwindow = meta_core_get_frame (display, client_xwindow);
if (frame_xwindow != None &&
meta_core_frame_has_grab (display, frame_xwindow, &device_id, NULL) ==
META_GRAB_OP_CLICKING_MENU)
{
Window grab_frame;
MetaUIFrame *frame;
grab_frame = meta_core_get_grab_frame (display);
frame = meta_frames_lookup_window (frames, frame_xwindow);
if (grab_frame != None)
if (frame)
{
MetaUIFrame *frame;
frame = meta_frames_lookup_window (frames, grab_frame);
if (frame)
{
redraw_control (frames, frame,
META_FRAME_CONTROL_MENU);
meta_core_end_grab_op (display, CurrentTime);
}
redraw_control (frames, frame,
META_FRAME_CONTROL_MENU);
meta_core_end_grab_op (display, device_id, CurrentTime);
}
}
}
@ -1450,7 +1466,10 @@ meta_frames_button_release_event (GtkWidget *widget,
MetaFrames *frames;
MetaGrabOp op;
Display *display;
int grab_button;
GdkDevice *device;
int device_id, grab_device_id;
frames = META_FRAMES (widget);
display = GDK_DISPLAY_XDISPLAY (gdk_display_get_default ());
@ -1458,17 +1477,21 @@ meta_frames_button_release_event (GtkWidget *widget,
if (frame == NULL)
return FALSE;
op = meta_core_get_grab_op (display);
op = meta_core_frame_has_grab (display, frame->xwindow,
&grab_device_id, &grab_button);
if (op == META_GRAB_OP_NONE)
device = gdk_event_get_device ((GdkEvent *) event);
device_id = gdk_x11_device_get_id (device);
if (op == META_GRAB_OP_NONE ||
grab_device_id != device_id)
return FALSE;
/* We only handle the releases we handled the presses for (things
* involving frame controls). Window ops that don't require a
* frame are handled in the Xlib part of the code, display.c/window.c
*/
if (frame->xwindow == meta_core_get_grab_frame (display) &&
((int) event->button) == meta_core_get_grab_button (display))
if (((int) event->button) == grab_button)
{
MetaFrameControl control;
@ -1479,8 +1502,8 @@ meta_frames_button_release_event (GtkWidget *widget,
case META_GRAB_OP_CLICKING_MINIMIZE:
if (control == META_FRAME_CONTROL_MINIMIZE)
meta_core_minimize (display, frame->xwindow);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_MAXIMIZE:
@ -1492,67 +1515,67 @@ meta_frames_button_release_event (GtkWidget *widget,
event->time);
meta_core_maximize (display, frame->xwindow);
}
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
if (control == META_FRAME_CONTROL_UNMAXIMIZE)
meta_core_unmaximize (display, frame->xwindow);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_DELETE:
if (control == META_FRAME_CONTROL_DELETE)
meta_core_delete (display, frame->xwindow, event->time);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_MENU:
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_SHADE:
if (control == META_FRAME_CONTROL_SHADE)
meta_core_shade (display, frame->xwindow, event->time);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_UNSHADE:
if (control == META_FRAME_CONTROL_UNSHADE)
meta_core_unshade (display, frame->xwindow, event->time);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_ABOVE:
if (control == META_FRAME_CONTROL_ABOVE)
meta_core_make_above (display, frame->xwindow);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_UNABOVE:
if (control == META_FRAME_CONTROL_UNABOVE)
meta_core_unmake_above (display, frame->xwindow);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_STICK:
if (control == META_FRAME_CONTROL_STICK)
meta_core_stick (display, frame->xwindow);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
case META_GRAB_OP_CLICKING_UNSTICK:
if (control == META_FRAME_CONTROL_UNSTICK)
meta_core_unstick (display, frame->xwindow);
meta_core_end_grab_op (display, event->time);
meta_core_end_grab_op (display, device_id, event->time);
break;
default:
@ -1564,7 +1587,9 @@ meta_frames_button_release_event (GtkWidget *widget,
* prelit so to let the user know that it can now be pressed.
* :)
*/
meta_frames_update_prelit_control (frames, frame, control);
meta_frames_update_prelit_control (frames, frame,
gdk_event_get_device ((GdkEvent *) event),
control);
}
return TRUE;
@ -1573,12 +1598,12 @@ meta_frames_button_release_event (GtkWidget *widget,
static void
meta_frames_update_prelit_control (MetaFrames *frames,
MetaUIFrame *frame,
GdkDevice *device,
MetaFrameControl control)
{
MetaFrameControl old_control;
MetaCursor cursor;
meta_verbose ("Updating prelit control from %u to %u\n",
frame->prelit_control, control);
@ -1643,6 +1668,7 @@ meta_frames_update_prelit_control (MetaFrames *frames,
/* set/unset the prelight cursor */
meta_core_set_screen_cursor (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
frame->xwindow,
gdk_x11_device_get_id (device),
cursor);
switch (control)
@ -1696,8 +1722,8 @@ meta_frames_motion_notify_event (GtkWidget *widget,
frames->last_motion_frame = frame;
grab_op = meta_core_get_grab_op (display);
grab_op = meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL);
switch (grab_op)
{
case META_GRAB_OP_CLICKING_MENU:
@ -1713,10 +1739,9 @@ meta_frames_motion_notify_event (GtkWidget *widget,
case META_GRAB_OP_CLICKING_UNSTICK:
{
MetaFrameControl control;
int x, y;
gdk_window_get_device_position (frame->window, event->device,
&x, &y, NULL);
gdouble x, y;
gdk_event_get_coords ((GdkEvent *) event, &x, &y);
/* Control is set to none unless it matches
* the current grab
@ -1747,21 +1772,23 @@ meta_frames_motion_notify_event (GtkWidget *widget,
control = META_FRAME_CONTROL_NONE;
/* Update prelit control and cursor */
meta_frames_update_prelit_control (frames, frame, control);
meta_frames_update_prelit_control (frames, frame,
gdk_event_get_device ((GdkEvent *) event),
control);
}
break;
case META_GRAB_OP_NONE:
{
MetaFrameControl control;
int x, y;
gdk_window_get_device_position (frame->window, event->device,
&x, &y, NULL);
gdouble x, y;
gdk_event_get_coords ((GdkEvent *) event, &x, &y);
control = get_control (frames, frame, x, y);
/* Update prelit control and cursor */
meta_frames_update_prelit_control (frames, frame, control);
meta_frames_update_prelit_control (frames, frame,
gdk_event_get_device ((GdkEvent *) event),
control);
}
break;
@ -1909,7 +1936,6 @@ meta_frames_paint (MetaFrames *frames,
GdkPixbuf *icon;
int w, h;
MetaButtonState button_states[META_BUTTON_TYPE_LAST];
Window grab_frame;
int i;
MetaButtonLayout button_layout;
MetaGrabOp grab_op;
@ -1920,11 +1946,8 @@ meta_frames_paint (MetaFrames *frames,
for (i = 0; i < META_BUTTON_TYPE_LAST; i++)
button_states[i] = META_BUTTON_STATE_NORMAL;
grab_frame = meta_core_get_grab_frame (display);
grab_op = meta_core_get_grab_op (display);
if (grab_frame != frame->xwindow)
grab_op = META_GRAB_OP_NONE;
grab_op = meta_core_frame_has_grab (display, frame->xwindow, NULL, NULL);
/* Set prelight state */
switch (frame->prelit_control)
{
@ -2085,7 +2108,9 @@ meta_frames_enter_notify_event (GtkWidget *widget,
return FALSE;
control = get_control (frames, frame, event->x, event->y);
meta_frames_update_prelit_control (frames, frame, control);
meta_frames_update_prelit_control (frames, frame,
gdk_event_get_device ((GdkEvent *) event),
control);
return TRUE;
}
@ -2103,7 +2128,9 @@ meta_frames_leave_notify_event (GtkWidget *widget,
if (frame == NULL)
return FALSE;
meta_frames_update_prelit_control (frames, frame, META_FRAME_CONTROL_NONE);
meta_frames_update_prelit_control (frames, frame,
gdk_event_get_device ((GdkEvent *) event),
META_FRAME_CONTROL_NONE);
return TRUE;
}

View File

@ -156,7 +156,8 @@ void meta_frames_move_resize_frame (MetaFrames *frames,
void meta_frames_queue_draw (MetaFrames *frames,
Window xwindow);
void meta_frames_notify_menu_hide (MetaFrames *frames);
void meta_frames_notify_menu_hide (MetaFrames *frames,
Window client_xwindow);
Window meta_frames_get_moving_frame (MetaFrames *frames);

View File

@ -137,7 +137,7 @@ menu_closed (GtkMenu *widget,
menu = data;
meta_frames_notify_menu_hide (menu->frames);
meta_frames_notify_menu_hide (menu->frames, menu->client_xwindow);
(* menu->func) (menu,
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
menu->client_xwindow,
@ -157,7 +157,7 @@ activate_cb (GtkWidget *menuitem, gpointer data)
md = data;
meta_frames_notify_menu_hide (md->menu->frames);
meta_frames_notify_menu_hide (md->menu->frames, md->menu->client_xwindow);
(* md->menu->func) (md->menu,
GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
md->menu->client_xwindow,
@ -498,13 +498,17 @@ meta_window_menu_new (MetaFrames *frames,
void
meta_window_menu_popup (MetaWindowMenu *menu,
MetaDevice *device,
int root_x,
int root_y,
int button,
guint32 timestamp)
{
GdkDeviceManager *device_manager;
GdkDevice *gdkdevice;
GdkDisplay *display;
GdkPoint *pt;
pt = g_new (GdkPoint, 1);
g_object_set_data_full (G_OBJECT (menu->menu),
@ -514,12 +518,18 @@ meta_window_menu_popup (MetaWindowMenu *menu,
pt->x = root_x;
pt->y = root_y;
gtk_menu_popup (GTK_MENU (menu->menu),
NULL, NULL,
popup_position_func, pt,
button,
timestamp);
display = gtk_widget_get_display (menu->menu);
device_manager = gdk_display_get_device_manager (display);
gdkdevice = gdk_x11_device_manager_lookup (device_manager,
meta_device_get_id (device));
gtk_menu_popup_for_device (GTK_MENU (menu->menu),
gdkdevice,
NULL, NULL,
popup_position_func, pt, NULL,
button,
timestamp);
if (!gtk_widget_get_visible (menu->menu))
meta_warning ("GtkMenu failed to grab the pointer\n");

View File

@ -25,6 +25,7 @@
#define META_MENU_H
#include <gtk/gtk.h>
#include <meta/device.h>
#include "frames.h"
/* Stock icons */
@ -52,6 +53,7 @@ MetaWindowMenu* meta_window_menu_new (MetaFrames *frames,
MetaWindowMenuFunc func,
gpointer data);
void meta_window_menu_popup (MetaWindowMenu *menu,
MetaDevice *device,
int root_x,
int root_y,
int button,

View File

@ -855,12 +855,21 @@ static WnckWindowDisplayInfo
meta_convert_meta_to_wnck (MetaWindow *window, MetaScreen *screen)
{
WnckWindowDisplayInfo wnck_window;
MetaFocusInfo *focus_info;
GHashTableIter iter;
wnck_window.icon = window->icon;
wnck_window.mini_icon = window->mini_icon;
wnck_window.is_active = FALSE;
if (window == window->display->expected_focus_window)
wnck_window.is_active = TRUE;
g_hash_table_iter_init (&iter, window->display->focus_info);
while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &focus_info))
{
if (window == focus_info->expected_focus_window)
wnck_window.is_active = TRUE;
}
if (window->frame)
{

View File

@ -148,6 +148,7 @@ meta_tile_preview_free (MetaTilePreview *preview)
void
meta_tile_preview_show (MetaTilePreview *preview,
MetaDevice *pointer,
MetaRectangle *tile_rect)
{
GdkWindow *window;
@ -164,6 +165,7 @@ meta_tile_preview_show (MetaTilePreview *preview,
window = gtk_widget_get_window (preview->preview_window);
meta_core_lower_beneath_grab_window (GDK_DISPLAY_XDISPLAY (gdk_display_get_default ()),
GDK_WINDOW_XID (window),
meta_device_get_id (pointer),
gtk_get_current_event_time ());
old_rect.x = old_rect.y = 0;

View File

@ -24,12 +24,14 @@
#define META_TILE_PREVIEW_H
#include <meta/boxes.h>
#include <meta/device.h>
typedef struct _MetaTilePreview MetaTilePreview;
MetaTilePreview *meta_tile_preview_new (int screen_number);
void meta_tile_preview_free (MetaTilePreview *preview);
void meta_tile_preview_show (MetaTilePreview *preview,
MetaDevice *pointer,
MetaRectangle *rect);
void meta_tile_preview_hide (MetaTilePreview *preview);
Window meta_tile_preview_get_xwindow (MetaTilePreview *preview,

View File

@ -30,6 +30,7 @@
#include "menu.h"
#include "core.h"
#include "theme-private.h"
#include "input-events.h"
#include "inlinepixbufs.h"
@ -60,15 +61,8 @@ struct _MetaUI
void
meta_ui_init (void)
{
/* As of 2.91.7, Gdk uses XI2 by default, which conflicts with the
* direct X calls we use - in particular, events caused by calls to
* XGrabPointer/XGrabKeyboard are no longer understood by GDK, while
* GDK will no longer generate the core XEvents we process.
* So at least for now, enforce the previous behavior.
*/
#if GTK_CHECK_VERSION(2, 91, 7)
gdk_disable_multidevice ();
#endif
if (meta_get_use_core_devices ())
gdk_disable_multidevice ();
if (!gtk_init_check (NULL, NULL))
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
@ -113,23 +107,25 @@ maybe_redirect_mouse_event (XEvent *xevent)
GdkEvent *gevent;
GdkWindow *gdk_window;
Window window;
MetaDisplay *display;
MetaDevice *device;
gdouble x, y, x_root, y_root;
guint evtype, n_button;
Time evtime;
switch (xevent->type)
{
case ButtonPress:
case ButtonRelease:
window = xevent->xbutton.window;
break;
case MotionNotify:
window = xevent->xmotion.window;
break;
case EnterNotify:
case LeaveNotify:
window = xevent->xcrossing.window;
break;
default:
return FALSE;
}
display = meta_display_for_x_display (xevent->xany.display);
if (!meta_input_event_get_type (display, xevent, &evtype))
return FALSE;
if (evtype != ButtonPress &&
evtype != ButtonRelease &&
evtype != EnterNotify &&
evtype != LeaveNotify &&
evtype != MotionNotify)
return FALSE;
window = meta_input_event_get_window (display, xevent);
gdisplay = gdk_x11_lookup_xdisplay (xevent->xany.display);
ui = g_object_get_data (G_OBJECT (gdisplay), "meta-ui");
@ -140,8 +136,14 @@ maybe_redirect_mouse_event (XEvent *xevent)
if (gdk_window == NULL)
return FALSE;
device = meta_input_event_get_device (display, xevent);
if (!device)
return FALSE;
gmanager = gdk_display_get_device_manager (gdisplay);
gdevice = gdk_device_manager_get_client_pointer (gmanager);
gdevice = gdk_x11_device_manager_lookup (gmanager,
meta_device_get_id (device));
/* If GDK already thinks it has a grab, we better let it see events; this
* is the menu-navigation case and events need to get sent to the appropriate
@ -150,11 +152,16 @@ maybe_redirect_mouse_event (XEvent *xevent)
if (gdk_display_device_is_grabbed (gdisplay, gdevice))
return FALSE;
switch (xevent->type)
evtime = meta_input_event_get_time (display, xevent);
meta_input_event_get_coordinates (display, xevent,
&x, &y, &x_root, &y_root);
switch (evtype)
{
case ButtonPress:
case ButtonRelease:
if (xevent->type == ButtonPress)
meta_input_event_get_button (display, xevent, &n_button);
if (evtype == ButtonPress)
{
GtkSettings *settings = gtk_settings_get_default ();
int double_click_time;
@ -165,11 +172,11 @@ maybe_redirect_mouse_event (XEvent *xevent)
"gtk-double-click-distance", &double_click_distance,
NULL);
if (xevent->xbutton.button == ui->button_click_number &&
xevent->xbutton.window == ui->button_click_window &&
xevent->xbutton.time < ui->button_click_time + double_click_time &&
ABS (xevent->xbutton.x - ui->button_click_x) <= double_click_distance &&
ABS (xevent->xbutton.y - ui->button_click_y) <= double_click_distance)
if (n_button == ui->button_click_number &&
window == ui->button_click_window &&
evtime < ui->button_click_time + double_click_time &&
ABS ((int) x - ui->button_click_x) <= double_click_distance &&
ABS ((int) y - ui->button_click_y) <= double_click_distance)
{
gevent = gdk_event_new (GDK_2BUTTON_PRESS);
@ -178,11 +185,11 @@ maybe_redirect_mouse_event (XEvent *xevent)
else
{
gevent = gdk_event_new (GDK_BUTTON_PRESS);
ui->button_click_number = xevent->xbutton.button;
ui->button_click_window = xevent->xbutton.window;
ui->button_click_time = xevent->xbutton.time;
ui->button_click_x = xevent->xbutton.x;
ui->button_click_y = xevent->xbutton.y;
ui->button_click_number = n_button;
ui->button_click_window = window;
ui->button_click_time = evtime;
ui->button_click_x = (int) x;
ui->button_click_y = (int) y;
}
}
else
@ -191,25 +198,29 @@ maybe_redirect_mouse_event (XEvent *xevent)
}
gevent->button.window = g_object_ref (gdk_window);
gevent->button.button = xevent->xbutton.button;
gevent->button.time = xevent->xbutton.time;
gevent->button.x = xevent->xbutton.x;
gevent->button.y = xevent->xbutton.y;
gevent->button.x_root = xevent->xbutton.x_root;
gevent->button.y_root = xevent->xbutton.y_root;
gevent->button.button = n_button;
gevent->button.time = evtime;
gevent->button.x = x;
gevent->button.y = y;
gevent->button.x_root = x_root;
gevent->button.y_root = y_root;
break;
case MotionNotify:
gevent = gdk_event_new (GDK_MOTION_NOTIFY);
gevent->motion.type = GDK_MOTION_NOTIFY;
gevent->motion.window = g_object_ref (gdk_window);
gevent->motion.x = x;
gevent->motion.y = y;
gevent->motion.x_root = x_root;
gevent->motion.y_root = y_root;
break;
case EnterNotify:
case LeaveNotify:
gevent = gdk_event_new (xevent->type == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
gevent = gdk_event_new (evtype == EnterNotify ? GDK_ENTER_NOTIFY : GDK_LEAVE_NOTIFY);
gevent->crossing.window = g_object_ref (gdk_window);
gevent->crossing.x = xevent->xcrossing.x;
gevent->crossing.y = xevent->xcrossing.y;
gevent->crossing.x = x;
gevent->crossing.y = y;
break;
default:
g_assert_not_reached ();
@ -402,7 +413,8 @@ meta_ui_create_frame_window (MetaUI *ui,
&attrs, attributes_mask);
gdk_window_resize (window, width, height);
gdk_window_set_support_multidevice (window, TRUE);
meta_frames_manage_window (ui->frames, GDK_WINDOW_XID (window), window);
return GDK_WINDOW_XID (window);
@ -530,12 +542,13 @@ meta_ui_window_menu_new (MetaUI *ui,
void
meta_ui_window_menu_popup (MetaWindowMenu *menu,
MetaDevice *device,
int root_x,
int root_y,
int button,
guint32 timestamp)
{
meta_window_menu_popup (menu, root_x, root_y, button, timestamp);
meta_window_menu_popup (menu, device, root_x, root_y, button, timestamp);
}
void

View File

@ -26,6 +26,7 @@
/* Don't include gtk.h or gdk.h here */
#include <meta/common.h>
#include <meta/device.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <cairo.h>
@ -131,6 +132,7 @@ MetaWindowMenu* meta_ui_window_menu_new (MetaUI *ui,
MetaWindowMenuFunc func,
gpointer data);
void meta_ui_window_menu_popup (MetaWindowMenu *menu,
MetaDevice *device,
int root_x,
int root_y,
int button,