Compare commits
69 Commits
METACITY_2
...
METACITY_2
Author | SHA1 | Date | |
---|---|---|---|
![]() |
e8bc8e95e2 | ||
![]() |
cfd3cdd64e | ||
![]() |
ec4edcb78c | ||
![]() |
94c3b02eef | ||
![]() |
f83ac8476c | ||
![]() |
4edccc4eb5 | ||
![]() |
0398a78b4a | ||
![]() |
ec6a455fb0 | ||
![]() |
e55ead0419 | ||
![]() |
f22b9dfd94 | ||
![]() |
ec4dfd0cbc | ||
![]() |
350ecb1dcf | ||
![]() |
38a878171a | ||
![]() |
dad1b107f5 | ||
![]() |
582a80f518 | ||
![]() |
808d21e857 | ||
![]() |
0a1f2b3a47 | ||
![]() |
4c104e1cb7 | ||
![]() |
ecf75915c7 | ||
![]() |
7be4c63ee4 | ||
![]() |
b09a781a80 | ||
![]() |
52dc32031d | ||
![]() |
a926a4a0ca | ||
![]() |
39df21227d | ||
![]() |
2830c9d748 | ||
![]() |
3886f0ecac | ||
![]() |
b1c7811e89 | ||
![]() |
1385d192c5 | ||
![]() |
82aa7363f9 | ||
![]() |
a4346200e8 | ||
![]() |
9f66f63bf5 | ||
![]() |
3645fef5e0 | ||
![]() |
f386494ba4 | ||
![]() |
936adc6ea5 | ||
![]() |
bc787fc1f3 | ||
![]() |
1c6c7350e1 | ||
![]() |
2a0a5dfdf8 | ||
![]() |
501dd26713 | ||
![]() |
3e1c68b88a | ||
![]() |
6d31d4756e | ||
![]() |
bea9d1f679 | ||
![]() |
4abbd4b1e5 | ||
![]() |
27c81cad33 | ||
![]() |
db0a7e2978 | ||
![]() |
4d2f018ddb | ||
![]() |
5eb43d34ff | ||
![]() |
ddfffe270f | ||
![]() |
cebbafdd22 | ||
![]() |
46082f8c71 | ||
![]() |
e51c12d1cd | ||
![]() |
f562e65d5f | ||
![]() |
04e09d4c56 | ||
![]() |
78a68f3e10 | ||
![]() |
b2444df787 | ||
![]() |
f70993be97 | ||
![]() |
92a965b979 | ||
![]() |
922749e5b3 | ||
![]() |
9acaa50f59 | ||
![]() |
60f531af35 | ||
![]() |
246ac5e578 | ||
![]() |
505282697a | ||
![]() |
6768aefb9d | ||
![]() |
fc8db63716 | ||
![]() |
d6bf2f5e80 | ||
![]() |
8c7b04edb9 | ||
![]() |
11b14d327f | ||
![]() |
d8561cb4c3 | ||
![]() |
47ce823aa5 | ||
![]() |
971419c880 |
421
ChangeLog
421
ChangeLog
@@ -1,3 +1,424 @@
|
||||
2001-10-13 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* configure.in: add bad hack to work with GTK 1.3.9.90 RPMs from
|
||||
gnomehide for now
|
||||
|
||||
* src/ui.c: another piece of bad hack in here
|
||||
|
||||
2001-10-13 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* configure.in: bump version
|
||||
|
||||
2001-10-13 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/session.c (meta_session_init): hmm, fix build
|
||||
|
||||
2001-10-12 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/session.c (meta_session_init): set the session manager
|
||||
priority so we start up before other apps.
|
||||
|
||||
2001-10-12 Mikael Hallendal <micke@codefactory.se>
|
||||
|
||||
* src/ui.c (meta_ui_get_default_window_icon): use
|
||||
gdk_pixbuf_new_from_inline
|
||||
(meta_ui_get_default_mini_icon): use
|
||||
gdk_pixbuf_new_from_inline
|
||||
|
||||
2001-10-11 Christian Rose <menthos@menthos.com>
|
||||
|
||||
* configure.in: Added "sv" to ALL_LINGUAS.
|
||||
|
||||
2001-10-10 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/stack.c (meta_stack_free): fix mem leak of the MetaStack
|
||||
object
|
||||
(meta_stack_sync_to_server): try to avoid the restack-flicker
|
||||
thing
|
||||
|
||||
2001-10-07 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/display.c (meta_display_update_active_window_hint):
|
||||
set _NET_ACTIVE_WINDOW hint
|
||||
|
||||
* src/window.c (meta_window_client_message): support
|
||||
_NET_ACTIVE_WINDOW client message
|
||||
|
||||
2001-10-07 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (meta_window_client_message): don't allow
|
||||
shade/maximize/minimize for windows that don't support those
|
||||
operations. (minimizing the panel = bad)
|
||||
|
||||
2001-10-04 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/keybindings.c (meta_change_keygrab): add code to grab all
|
||||
modifier combinations, so keybindings work with NumLock etc.
|
||||
|
||||
* src/menu.c (meta_window_menu_new): remove newlines from menu
|
||||
items
|
||||
|
||||
2001-09-27 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/session.c (save_state): when encoding text for session file,
|
||||
escape XML entities
|
||||
|
||||
2001-09-21 Alex Graveley <alex@ximian.com>
|
||||
|
||||
* src/Makefile.am (metacity_SOURCES): Add inlinepixbufs.h so
|
||||
that it gets generated.
|
||||
|
||||
* src/frames.c (meta_frames_style_set): Update for new opaque
|
||||
PangoFontMetrics.
|
||||
|
||||
2001-09-17 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/ui.c (meta_ui_init): add hackaround for the warning about
|
||||
gtk-menu-bar-accel
|
||||
|
||||
2001-09-17 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/ui.c (meta_ui_get_default_mini_icon):
|
||||
(meta_ui_get_default_window_icon): ref the returned icon, oops.
|
||||
|
||||
* src/main.c (main): get the GLib warning/error output into
|
||||
the metacity logfile, set warnings to be always fatal
|
||||
|
||||
* configure.in: bump version to 2.3.13
|
||||
|
||||
* src/window.c (get_text_property): hrm, fix bug where we didn't
|
||||
check errors on XGetTextProperty
|
||||
|
||||
2001-09-17 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/Makefile.am (VARIABLES): fix srcdir != builddir glitch
|
||||
|
||||
2001-09-17 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/ui.c: use the inline image data for default icon
|
||||
|
||||
* src/common.h (META_MINI_ICON_HEIGHT): move icon size defines
|
||||
here
|
||||
|
||||
* src/Makefile.am: Create an inlinepixbufs.h header with inline
|
||||
images
|
||||
|
||||
2001-09-16 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/session.c (process_ice_messages): disconnect this callback
|
||||
on error
|
||||
|
||||
2001-09-16 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (meta_window_lower): new function
|
||||
|
||||
* configure.in: bump version to 2.3.8
|
||||
|
||||
* src/display.c (event_callback): raise dock on enter notify,
|
||||
lower it on leave notify (need to refine this behavior)
|
||||
|
||||
* src/stack.c (compute_layer): experiment with putting the panel
|
||||
in the normal layer, and raising it on mouseover
|
||||
|
||||
2001-09-15 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c: add support for a mini icon in the titlebar
|
||||
(update_icon): re-enable support for _NET_WM_ICON
|
||||
|
||||
* src/session.c (save_state): add an ferror check when writing
|
||||
session file
|
||||
|
||||
2001-09-11 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/main.c (usage): exit with error code on usage() (kind of
|
||||
wrong for --help, but oh well).
|
||||
|
||||
2001-09-11 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c: fix up handling of text properties, so we
|
||||
get UTF8_STRING as that type and not as text list, and so
|
||||
we properly convert from text list to UTF-8
|
||||
|
||||
2001-09-10 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/menu.c (meta_window_menu_new): icon for unmaximize
|
||||
|
||||
* src/ui.c (meta_ui_init): fix call to XDisplayName
|
||||
|
||||
* src/util.c: add missing header
|
||||
|
||||
* src/frames.c: draw an unmaximize control if already maximized
|
||||
|
||||
2001-09-10 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c: Don't separate user_has_moved/user_has_resized,
|
||||
fixes bug in east-resizing Emacs, among other things
|
||||
|
||||
* src/frame.c (meta_frame_sync_to_window): return immediately if
|
||||
nothing to do
|
||||
|
||||
* src/util.c (ensure_logfile): replace rather than truncate old
|
||||
logfiles
|
||||
|
||||
2001-09-08 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/ui.c (meta_ui_init): don't use gdk_display_name
|
||||
|
||||
* src/frame.c (meta_window_ensure_frame): create frame
|
||||
with screen default visual, rather than client window visual;
|
||||
for DRI games, the client window visual was not allowed to be
|
||||
a child of another window with the same visual, apparently.
|
||||
Anyhow now we copy twm, etc. so it must be correct.
|
||||
|
||||
* src/place.c (meta_window_place): if a transient is placed and
|
||||
its parent has focus, focus the transient.
|
||||
|
||||
2001-09-06 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* configure.in: bump version 2.3.5, require newer GTK release
|
||||
|
||||
2001-09-04 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/wm-tester/Makefile.am (noinst_PROGRAMS): make test apps
|
||||
noinst
|
||||
|
||||
* src/metacity.desktop: for the capplet
|
||||
|
||||
* src/Makefile.am: add .desktop file
|
||||
|
||||
2001-09-01 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/errors.c: clean up the code, and replace GDK X error handler
|
||||
with one that chains up to GDK but first logs the error to logfile.
|
||||
|
||||
2001-08-31 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/tabpopup.c (meta_ui_tab_popup_new): fix args to
|
||||
gtk_alignment_new()
|
||||
|
||||
2001-08-29 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/display.c (event_callback): avoid focusing a window on tab
|
||||
popup popdown
|
||||
|
||||
* src/screen.c (meta_screen_ensure_tab_popup): compute frame
|
||||
outline size here
|
||||
|
||||
2001-08-29 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* src/tabpopup.c: Switch back to outline.
|
||||
|
||||
2001-08-29 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/tabpopup.c: experiment with window-cover-with-icon
|
||||
instead of just the outline; can't decide.
|
||||
|
||||
2001-08-29 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/tabpopup.c: add crackrock window-outlining feature
|
||||
|
||||
* src/session.c (window_type_to_string): handle fullscreen
|
||||
|
||||
2001-08-29 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/display.c (meta_display_open): wrong atom name -
|
||||
_NET_SUPPORTED not _NET_WM_SUPPORTED
|
||||
|
||||
* src/window.c (meta_window_configure_request): geez, why were we
|
||||
honoring configure requests for width/height for normal windows.
|
||||
Denied!
|
||||
(meta_window_client_message): _NET_WM_MOVERESIZE support, sort of
|
||||
(doesn't quite work, acts like owner_events = true?)
|
||||
|
||||
* src/display.c: add _NET_WM_MOVERESIZE atom
|
||||
|
||||
2001-08-28 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
Unbreak tab popup a bit.
|
||||
|
||||
* src/stack.c (meta_stack_get_tab_list): add workspace argument
|
||||
(meta_stack_get_tab_next): add workspace argument
|
||||
|
||||
* src/window.c: implement recording of the last user-initiated
|
||||
window position, so we can magically handle moving panels around
|
||||
really nicely.
|
||||
|
||||
* src/wm-tester/main.c (set_up_icon_windows): fix to use new GTK
|
||||
API
|
||||
|
||||
2001-08-24 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (constrain_position): force fullscreen windows to
|
||||
be at 0,0
|
||||
|
||||
* src/ui.c: use NULL colormap to get bitmaps, requires
|
||||
very latest GTK from CVS or it will spew warnings
|
||||
and not work.
|
||||
|
||||
* src/window.c (constrain_size): disallow larger than screen in
|
||||
all cases, even if user has performed a resize operation.
|
||||
(constrain_position): keep window boxed onscreen.
|
||||
|
||||
* src/keybindings.c (meta_display_process_key_event): revert an
|
||||
earlier change that disabled global keybindings when a grab is in
|
||||
effect; instead, only disable global keybindings if a _keyboard_
|
||||
grab is in effect. The earlier change was just a broken
|
||||
workaround, the problems it fixed should have been solved by the
|
||||
addition of XGrabKeyboard() on the metacity keyboard grabs.
|
||||
|
||||
This should fix the problem with
|
||||
pick-up-window-and-move-to-another-desktop.
|
||||
|
||||
2001-08-23 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (update_icon): attempt to use the mask as well as
|
||||
the pixmap. Probably doesn't work so well.
|
||||
|
||||
* src/tabpopup.c: make this look a little nicer
|
||||
|
||||
2001-08-22 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (update_mwm_hints): all the MWM flag tests were
|
||||
backward
|
||||
|
||||
2001-08-22 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (update_icon): half-ass implementation of
|
||||
getting pixmap icons (WM_NORMAL_HINTS and KWM_WIN_ICON).
|
||||
Ignores mask for now, with possibly ugly results for
|
||||
some apps.
|
||||
(read_rgb_icon): fixage
|
||||
|
||||
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c: add a "fullscreen" semantic type; if a window
|
||||
requests the screen size exactly, and is undecorated, and is not a
|
||||
desktop window, we consider it a fullscreen window and keep it on
|
||||
top.
|
||||
|
||||
Totally untested.
|
||||
|
||||
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/screen.c (set_supported_hint): we support _NET_WM_ICON
|
||||
|
||||
* src/wm-tester/main.c: add stuff to test _NET_WM_ICON
|
||||
(but it doesn't work, so it isn't tested yet)
|
||||
|
||||
* src/window.c (update_icon): read _NET_WM_ICON
|
||||
|
||||
* src/screen.c (meta_screen_new): set the WM_ICON_SIZE hint
|
||||
|
||||
* src/tabpopup.c (meta_ui_tab_popup_select): remove assertion
|
||||
|
||||
* src/window.c (meta_window_get_icon_geometry): fix obscure
|
||||
memleak
|
||||
|
||||
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/display.c (meta_display_grab_window_buttons): remove XSync,
|
||||
error traps already do that
|
||||
(meta_display_grab_window_buttons): implement
|
||||
|
||||
* src/keybindings.c:
|
||||
src/display.c: wire up the tab window, it rulez!
|
||||
|
||||
2001-08-19 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/tabpopup.c: add prototype thingy to display windows we're
|
||||
cycling through with tab. Not wired up to keybindings yet.
|
||||
|
||||
2001-08-18 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/effects.c (meta_effects_draw_box_animation): put an XFlush()
|
||||
right after starting things moving
|
||||
|
||||
2001-08-18 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (meta_window_configure_request):
|
||||
(meta_window_move_resize_internal): Make a half-hearted
|
||||
not-very-tested attempt to handle window resizes correctly with
|
||||
respect to window gravity.
|
||||
|
||||
2001-08-18 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (meta_window_get_gravity_position): hrm, I fixed
|
||||
this wrong the other day. Fixes static gravity when moving
|
||||
windows.
|
||||
|
||||
2001-08-18 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/ui.c (meta_image_window_set_position): also set the current
|
||||
size. Lame hack of the day.
|
||||
|
||||
* src/effects.c (effects_draw_box_animation_timeout): use the
|
||||
delay exposes feature to avoid the screen dirt
|
||||
|
||||
* src/ui.c
|
||||
(meta_ui_push_delay_exposes):
|
||||
(meta_ui_pop_delay_exposes): feature to let us delay redraws until
|
||||
after we do server-grabbed draw-on-inferiors effects
|
||||
|
||||
2001-08-17 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* src/window.c (meta_window_get_gravity_position): fix for
|
||||
StaticGravity
|
||||
|
||||
2001-08-09 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/window.c (meta_window_configure_request): Honor USPosition
|
||||
even post-map. I know I'll regret this.
|
||||
|
||||
2001-08-07 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/display.c (meta_display_open): set _NET_WM_NAME
|
||||
hint as a UTF8_STRING not STRING. Patch from Anders.
|
||||
|
||||
2001-08-06 Havoc Pennington <hp@redhat.com>
|
||||
|
||||
* src/effects.c: disable opaque animations by default, current
|
||||
implementation suXors.
|
||||
|
||||
2001-08-06 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/effects.c (meta_effects_draw_box_animation): Get start
|
||||
time after we do the pixbuf from drawable, so we don't count
|
||||
time spent getting pixbuf from drawable in the animation time.
|
||||
|
||||
2001-08-06 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/effects.c: add opaque minimize/shade feature. The wireframe
|
||||
seemed kind of confusing and unclear from a UI standpoint.
|
||||
I know, I know. The bloat begins here.
|
||||
|
||||
Also, we don't need to grab the server during opaque min/shade,
|
||||
which has some nice implications.
|
||||
|
||||
* src/ui.c: Add features to render a window with an image in it,
|
||||
and also wrap pixbuf_from_drawable
|
||||
|
||||
* src/effects.c (meta_effects_draw_box_animation):
|
||||
modify to be smoother (at least theoretically) by
|
||||
syncing to current time and "dropping frames"
|
||||
as appropriate.
|
||||
|
||||
* src/window.c (meta_window_shade): draw animation
|
||||
for shading too
|
||||
|
||||
2001-08-05 Anders Carlsson <andersca@gnu.org>
|
||||
|
||||
* src/display.h, src/display.c: Add _NET_WM_ICON_GEOMETRY atom.
|
||||
|
||||
* src/window.c (meta_window_calc_showing): See if the window has
|
||||
an icon geometry and show a morphing animation from the window's
|
||||
coordinates to the icon's coordinates.
|
||||
(meta_window_get_icon_geometry): New function that fetches a
|
||||
window's icon geometry.
|
||||
|
||||
* src/Makefile.am: Add effects.[ch].
|
||||
|
||||
* src/effects.c: New file with cool effects.
|
||||
|
||||
2001-08-03 Havoc Pennington <hp@pobox.com>
|
||||
|
||||
* src/keybindings.c: Add Alt + left/right arrow to
|
||||
|
4
HACKING
4
HACKING
@@ -1,4 +1,8 @@
|
||||
|
||||
Don't commit substantive code in here without asking me,
|
||||
hp@redhat.com. Adding translations, no-brainer typo fixes, etc. is
|
||||
fine.
|
||||
|
||||
The script src/run-metacity.sh is useful to hack on the window manager.
|
||||
It runs metacity in an Xnest. e.g.:
|
||||
CLIENTS=3 ./run-metacity.sh
|
||||
|
44
README
44
README
@@ -9,19 +9,24 @@ your petty hangups about version numbers.
|
||||
COMPILING METACITY
|
||||
===
|
||||
|
||||
You need GTK+ 1.3.x (to become 2.0). At the moment CVS HEAD is
|
||||
required. Once 1.3.7 is available that will probably work. Metacity is
|
||||
a fairly trivial 6000-line C program, so once you get GTK+ built it
|
||||
should be no problem to build Metacity.
|
||||
You need GTK+ 1.3.x (to become 2.0), at least version 1.3.9. At the
|
||||
moment CVS HEAD works, but that can change. Metacity is a fairly
|
||||
trivial 6000-line C program, so once you get GTK+ built it should be
|
||||
no problem to build Metacity.
|
||||
|
||||
There are SRPMs and sometimes RPMs on the ftp site, but you'd be
|
||||
pretty lucky to get them to work for now, since they are often out of
|
||||
sync with GTK. You might try with the GTK from ftp.gtk.org, and also
|
||||
the GTK from http://people.redhat.com/hp/gnomehide/.
|
||||
|
||||
REPORTING BUGS AND SUBMITTING PATCHES
|
||||
===
|
||||
|
||||
Report new bugs to hp@redhat.com for now. Will switch to Bugzilla
|
||||
sometime probably.
|
||||
Report new bugs on http://bugzilla.gnome.org.
|
||||
|
||||
Feel free to send patches too; Metacity is really small and simple, so
|
||||
if you find a bug or want to add a feature it should be pretty easy.
|
||||
Send me mail, or put the patch in bugzilla.
|
||||
|
||||
See the HACKING file for some notes on hacking Metacity.
|
||||
|
||||
@@ -123,6 +128,13 @@ METACITY FEATURES
|
||||
- Uses Pango to render text, so has cool i18n capabilities.
|
||||
Supports UTF-8 window titles and such.
|
||||
|
||||
- There are simple animations for actions such as minimization,
|
||||
to help users see what is happening. Should probably
|
||||
have a few more of these.
|
||||
|
||||
- if you have the proper X setup, set the GDK_USE_XFT=1
|
||||
environment variable to get antialiased window titles.
|
||||
|
||||
METACITY BUGS, NON-FEATURES, AND CAVEATS
|
||||
===
|
||||
|
||||
@@ -139,6 +151,8 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
|
||||
clicking the minimize button is sort of a bad idea.
|
||||
(If you had a WM-spec-compliant tasklist, it would work
|
||||
for unminimization.)
|
||||
(Update: you can use "test-wnck" from the libwnck CVS module to
|
||||
unminimize, but it's not much of a UI ;-)
|
||||
|
||||
- Metacity uses the new window manager spec, but only random bits of
|
||||
the old GNOME spec. It correctly advertises exactly which parts of
|
||||
@@ -158,17 +172,7 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
|
||||
instead of Alt as the main keybinding shortcut, if super/hyper
|
||||
exist, and then keyboards with a windows key can use that for
|
||||
WM functions and Alt for application shortcuts.
|
||||
We'd fall back to Alt if no other suitable modifier existed.
|
||||
|
||||
- Cycling windows with Alt-Tab is flickery, AFAIK because
|
||||
Metacity passes the entire window stack to XRestackWindows()
|
||||
every time you restack. Instead it should probably only restack
|
||||
windows that have changed their stacking with respect to one
|
||||
another. (But sometimes I don't see the flicker, so
|
||||
I'm not sure.)
|
||||
|
||||
- Various operations, such as minimize, maximize, etc., should
|
||||
have simple animations to make them clearer to users.
|
||||
We'd fall back to Alt if no other suitable modifier existed.
|
||||
|
||||
- I haven't even read the ICCCM section about colormaps. So if you
|
||||
have an 8-bit display you are basically screwed.
|
||||
@@ -193,10 +197,6 @@ METACITY BUGS, NON-FEATURES, AND CAVEATS
|
||||
|
||||
- Should support click-to-focus as an option.
|
||||
|
||||
- Windows has a neat way of implementing Alt-Tab for
|
||||
window cycling that I would like to copy. (The little
|
||||
popup window thing.)
|
||||
|
||||
- Should Metacity support flipping in right-to-left locales?
|
||||
I don't know what window managers look like in a right-to-left
|
||||
locale. I assume the window titles should be right-justified;
|
||||
@@ -272,6 +272,8 @@ A: If it makes sense to turn on unconditionally,
|
||||
probably constitute crackrock, they confuse most users
|
||||
and really are not that useful if you have a decent tasklist and
|
||||
so on. But I am too used to them to turn them off.
|
||||
Or alternatively iconification/tasklist is crack, and workspaces/pager
|
||||
are good. But having both is certainly a bit wrong.
|
||||
Sloppy focus is probably crackrock too. Oh, and my Alt-1 thru Alt-6
|
||||
keybindings are definitely on crack.
|
||||
|
||||
|
25
configure.in
25
configure.in
@@ -2,7 +2,7 @@ AC_INIT(src/display.c)
|
||||
|
||||
AM_CONFIG_HEADER(config.h)
|
||||
|
||||
AM_INIT_AUTOMAKE(metacity, 2.3.2)
|
||||
AM_INIT_AUTOMAKE(metacity, 2.3.21)
|
||||
|
||||
GETTEXT_PACKAGE=metacity
|
||||
AC_SUBST(GETTEXT_PACKAGE)
|
||||
@@ -37,11 +37,11 @@ if test "x$GCC" = "xyes"; then
|
||||
fi
|
||||
changequote([,])dnl
|
||||
|
||||
ALL_LINGUAS=""
|
||||
ALL_LINGUAS="sv"
|
||||
dnl AM_GNU_GETTEXT
|
||||
|
||||
## here we get the flags we'll actually use
|
||||
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 1.3.6)
|
||||
PKG_CHECK_MODULES(METACITY, gtk+-2.0 >= 1.3.9)
|
||||
|
||||
CFLAGS="$METACITY_CFLAGS $CFLAGS"
|
||||
|
||||
@@ -62,16 +62,27 @@ if test "$found_sm" = "true"; then
|
||||
AC_DEFINE(HAVE_SM)
|
||||
fi
|
||||
|
||||
# Check for shaped window extension
|
||||
AC_CHECK_LIB(Xext, XShapeCombineMask, AC_DEFINE(HAVE_SHAPE_EXT),,$METACITY_LIBS)
|
||||
AM_CONDITIONAL(HAVE_SM, test "$found_sm" = "true")
|
||||
|
||||
HOST_ALIAS=$host_alias
|
||||
AC_SUBST(HOST_ALIAS)
|
||||
|
||||
AC_PATH_PROG(GDK_PIXBUF_CSOURCE, gdk-pixbuf-csource, no)
|
||||
|
||||
if test x"$GDK_PIXBUF_CSOURCE" = xno; then
|
||||
AC_MSG_ERROR([gdk-pixbuf-csource executable not found in your path - should be installed with GTK])
|
||||
fi
|
||||
|
||||
AC_SUBST(GDK_PIXBUF_CSOURCE)
|
||||
|
||||
## hack to work with old GTK versions for now
|
||||
save_LDFLAGS=$LDFLAGS
|
||||
LDFLAGS="$METACITY_LIBS $LDFLAGS"
|
||||
AC_CHECK_FUNCS(gdk_pixbuf_new_from_stream)
|
||||
LDFLAGS=$save_LDFLAGS
|
||||
|
||||
AC_OUTPUT([
|
||||
Makefile
|
||||
src/Makefile
|
||||
src/wm-tester/Makefile
|
||||
])
|
||||
|
||||
|
||||
|
@@ -4,3 +4,5 @@ Makefile.in
|
||||
Makefile
|
||||
stamp-cat-id
|
||||
cat-id-tbl.c
|
||||
messages
|
||||
*.pot
|
||||
|
11
po/ChangeLog
Normal file
11
po/ChangeLog
Normal file
@@ -0,0 +1,11 @@
|
||||
2001-10-11 Christian Rose <menthos@menthos.com>
|
||||
|
||||
* sv.po: Fixed some typos. Thanks to Tomas <20>gren <stric@ing.umu.se>
|
||||
for spotting many of them.
|
||||
|
||||
2001-10-11 Christian Rose <menthos@menthos.com>
|
||||
|
||||
* sv.po: Added Swedish translation.
|
||||
* POTFILES.in: Added files.
|
||||
* .cvsignore: Added messages and *.pot.
|
||||
|
@@ -0,0 +1,8 @@
|
||||
src/display.c
|
||||
src/errors.c
|
||||
src/frames.c
|
||||
src/keybindings.c
|
||||
src/menu.c
|
||||
src/screen.c
|
||||
src/session.c
|
||||
src/window.c
|
||||
|
306
po/sv.po
Normal file
306
po/sv.po
Normal file
@@ -0,0 +1,306 @@
|
||||
# Swedish messages for metacity.
|
||||
# Copyright (C) 2001 Free Software Foundation, Inc.
|
||||
# Christian Rose <menthos@menthos.com>, 2001.
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: metacity\n"
|
||||
"POT-Creation-Date: 2001-10-11 12:59+0200\n"
|
||||
"PO-Revision-Date: 2001-10-11 13:04+0200\n"
|
||||
"Last-Translator: Christian Rose <menthos@menthos.com>\n"
|
||||
"Language-Team: Swedish <sv@li.org>\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=iso-8859-1\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
|
||||
#: src/display.c:153
|
||||
#, c-format
|
||||
msgid "Failed to open X Window System display '%s'\n"
|
||||
msgstr "Misslyckades med att <20>ppna X Window System-displayen \"%s\"\n"
|
||||
|
||||
#: src/errors.c:92
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Lost connection to the display '%s';\n"
|
||||
"most likely the X server was shut down or you killed/destroyed\n"
|
||||
"the window manager.\n"
|
||||
msgstr ""
|
||||
"Tappade anslutningen till displayen \"%s\";\n"
|
||||
"troligtvis st<73>ngdes X-servern ner, eller s<> d<>dade/f<>rst<73>rde du\n"
|
||||
"f<>nsterhanteraren.\n"
|
||||
|
||||
#: src/errors.c:99
|
||||
#, c-format
|
||||
msgid "Fatal IO error %d (%s) on display '%s'.\n"
|
||||
msgstr "<22>desdigert IO-fel %d (%s) p<> display \"%s\".\n"
|
||||
|
||||
#: src/frames.c:229
|
||||
msgid "Left edge"
|
||||
msgstr "V<>nsterkant"
|
||||
|
||||
#: src/frames.c:229
|
||||
msgid "Left window edge width"
|
||||
msgstr "Bredd p<> v<>nster f<>nsterkant"
|
||||
|
||||
#: src/frames.c:230
|
||||
msgid "Right edge"
|
||||
msgstr "H<>gerkant"
|
||||
|
||||
#: src/frames.c:230
|
||||
msgid "Right window edge width"
|
||||
msgstr "Bredd p<> h<>ger f<>nsterkant"
|
||||
|
||||
#: src/frames.c:231
|
||||
msgid "Bottom edge"
|
||||
msgstr "Nederkant"
|
||||
|
||||
#: src/frames.c:231
|
||||
msgid "Bottom window edge height"
|
||||
msgstr "H<>jd p<> nedre f<>nsterkant"
|
||||
|
||||
#: src/frames.c:233
|
||||
msgid "Title border"
|
||||
msgstr "Titelkant"
|
||||
|
||||
#: src/frames.c:233
|
||||
msgid "Border around title area"
|
||||
msgstr "Ram runt titelomr<6D>det"
|
||||
|
||||
#: src/frames.c:234
|
||||
msgid "Text border"
|
||||
msgstr "Textram"
|
||||
|
||||
#: src/frames.c:234
|
||||
msgid "Border around window title text"
|
||||
msgstr "Ram runt f<>nstertiteln"
|
||||
|
||||
#: src/frames.c:236
|
||||
msgid "Spacer padding"
|
||||
msgstr "Utfyllnadsmellanrum"
|
||||
|
||||
#: src/frames.c:236
|
||||
msgid "Padding on either side of spacer"
|
||||
msgstr "Utfyllnad p<> varje sida om utfyllare"
|
||||
|
||||
#: src/frames.c:237
|
||||
msgid "Spacer width"
|
||||
msgstr "Utfyllnadsbredd"
|
||||
|
||||
#: src/frames.c:237
|
||||
msgid "Width of spacer"
|
||||
msgstr "Bredd p<> utfyllnad"
|
||||
|
||||
#: src/frames.c:238
|
||||
msgid "Spacer height"
|
||||
msgstr "Utfyllnadsh<73>jd"
|
||||
|
||||
#: src/frames.c:238
|
||||
msgid "Height of spacer"
|
||||
msgstr "H<>jd p<> utfyllnad"
|
||||
|
||||
#. same as right_width left_width by default
|
||||
#: src/frames.c:241
|
||||
msgid "Right inset"
|
||||
msgstr "H<>ger inf<6E>llning"
|
||||
|
||||
#: src/frames.c:241
|
||||
msgid "Distance of buttons from right edge of frame"
|
||||
msgstr "Avst<73>nd p<> knappar fr<66>n h<>gerkanten p<> ramen"
|
||||
|
||||
#: src/frames.c:242
|
||||
msgid "Left inset"
|
||||
msgstr "V<>nster inf<6E>llning"
|
||||
|
||||
#: src/frames.c:242
|
||||
msgid "Distance of menu button from left edge of frame"
|
||||
msgstr "Avst<73>nd p<> menyknapp fr<66>n v<>nsterkanten p<> ramen"
|
||||
|
||||
#: src/frames.c:244
|
||||
msgid "Button width"
|
||||
msgstr "Knappbredd"
|
||||
|
||||
#: src/frames.c:244
|
||||
msgid "Width of buttons"
|
||||
msgstr "Bredd p<> knappar"
|
||||
|
||||
#: src/frames.c:245
|
||||
msgid "Button height"
|
||||
msgstr "Knapph<70>jd"
|
||||
|
||||
#: src/frames.c:245
|
||||
msgid "Height of buttons"
|
||||
msgstr "H<>jd p<> knappar"
|
||||
|
||||
#: src/frames.c:247
|
||||
msgid "Button border"
|
||||
msgstr "Knappram"
|
||||
|
||||
#: src/frames.c:247
|
||||
msgid "Border around buttons"
|
||||
msgstr "Ram runt knappar"
|
||||
|
||||
#: src/frames.c:248
|
||||
msgid "Inner button border"
|
||||
msgstr "Inre knappram"
|
||||
|
||||
#: src/frames.c:248
|
||||
msgid "Border around the icon inside buttons"
|
||||
msgstr "Ram runt ikonen inuti knappar"
|
||||
|
||||
#: src/frames.c:883
|
||||
msgid "Close Window"
|
||||
msgstr "St<53>ng f<>nster"
|
||||
|
||||
#: src/frames.c:886
|
||||
msgid "Window Menu"
|
||||
msgstr "F<>nstermeny"
|
||||
|
||||
#: src/frames.c:889
|
||||
msgid "Minimize Window"
|
||||
msgstr "Minimera f<>nster"
|
||||
|
||||
#: src/frames.c:892
|
||||
msgid "Maximize Window"
|
||||
msgstr "Maximera f<>nster"
|
||||
|
||||
#: src/frames.c:895
|
||||
msgid "Unmaximize Window"
|
||||
msgstr "Avmaximera f<>nster"
|
||||
|
||||
#: src/keybindings.c:203
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Some other program is already using the key %s with modifiers %x as a "
|
||||
"binding\n"
|
||||
msgstr ""
|
||||
"Ett annat program anv<6E>nder redan tangenten %s med modifierarna %x som en "
|
||||
"bindning\n"
|
||||
|
||||
#: src/menu.c:47
|
||||
msgid "_Close"
|
||||
msgstr "_St<53>ng"
|
||||
|
||||
#: src/menu.c:48
|
||||
msgid "_Minimize"
|
||||
msgstr "_Minimera"
|
||||
|
||||
#: src/menu.c:49
|
||||
msgid "Ma_ximize"
|
||||
msgstr "Ma_ximera"
|
||||
|
||||
#: src/menu.c:50
|
||||
msgid "_Unmaximize"
|
||||
msgstr "_Avmaximera"
|
||||
|
||||
#: src/menu.c:51
|
||||
msgid "_Shade"
|
||||
msgstr "_Skugga"
|
||||
|
||||
#: src/menu.c:52
|
||||
msgid "U_nshade"
|
||||
msgstr "A_vskugga"
|
||||
|
||||
#: src/menu.c:53
|
||||
msgid "Mo_ve"
|
||||
msgstr "Fl_ytta"
|
||||
|
||||
#: src/menu.c:54
|
||||
msgid "_Resize"
|
||||
msgstr "_<>ndra storlek"
|
||||
|
||||
#. separator
|
||||
#: src/menu.c:56
|
||||
msgid "Put on _All Workspaces"
|
||||
msgstr "Placera p<> _alla arbetsytor"
|
||||
|
||||
#: src/menu.c:57
|
||||
msgid "Only on _This Workspace"
|
||||
msgstr "Endast p<> _denna arbetsyta"
|
||||
|
||||
#: src/menu.c:260
|
||||
#, c-format
|
||||
msgid "Only on workspace _%d"
|
||||
msgstr "Endast p<> arbetsyta _%d"
|
||||
|
||||
#: src/menu.c:263
|
||||
#, c-format
|
||||
msgid "Move to workspace _%d"
|
||||
msgstr "Flytta till arbetsyta _%d"
|
||||
|
||||
#: src/screen.c:168
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' is invalid\n"
|
||||
msgstr "Sk<53>rm %d p<> display \"%s\" <20>r ogiltig\n"
|
||||
|
||||
#: src/screen.c:183
|
||||
#, c-format
|
||||
msgid "Screen %d on display '%s' already has a window manager\n"
|
||||
msgstr "Sk<53>rm %d p<> display \"%s\" har redan en f<>nsterhanterare\n"
|
||||
|
||||
#: src/session.c:742 src/session.c:749
|
||||
#, c-format
|
||||
msgid "Could not create directory '%s': %s\n"
|
||||
msgstr "Kunde inte skapa katalogen \"%s\": %s\n"
|
||||
|
||||
#: src/session.c:759
|
||||
#, c-format
|
||||
msgid "Could not open session file '%s' for writing: %s\n"
|
||||
msgstr "Kunde inte <20>ppna sessionsfilen \"%s\" f<>r skrivning: %s\n"
|
||||
|
||||
#: src/session.c:891
|
||||
#, c-format
|
||||
msgid "Error writing session file '%s': %s\n"
|
||||
msgstr "Fel vid skrivning av sessionsfilen \"%s\": %s\n"
|
||||
|
||||
#: src/session.c:896
|
||||
#, c-format
|
||||
msgid "Error closing session file '%s': %s\n"
|
||||
msgstr "Fel vid st<73>ngning av sessionsfilen \"%s\": %s\n"
|
||||
|
||||
#: src/session.c:970
|
||||
#, c-format
|
||||
msgid "Failed to read saved session file %s: %s\n"
|
||||
msgstr "Misslyckades med att l<>sa sparad sessionsfil %s: %s\n"
|
||||
|
||||
#: src/session.c:1004
|
||||
#, c-format
|
||||
msgid "Failed to parse saved session file: %s\n"
|
||||
msgstr "Misslyckades med att tolka sparad sessionsfil: %s\n"
|
||||
|
||||
#: src/session.c:1042
|
||||
msgid "nested <window> tag"
|
||||
msgstr "n<>stlad <window>-tagg"
|
||||
|
||||
#: src/session.c:1092 src/session.c:1124
|
||||
#, c-format
|
||||
msgid "Unknown attribute %s on <window> element"
|
||||
msgstr "Ok<4F>nt attribut %s p<> <window>-element"
|
||||
|
||||
#: src/session.c:1184
|
||||
#, c-format
|
||||
msgid "Unknown attribute %s on <geometry> element"
|
||||
msgstr "Ok<4F>nt attribut %s p<> <geometry>-element"
|
||||
|
||||
#: src/session.c:1204
|
||||
#, c-format
|
||||
msgid "Unknown element %s"
|
||||
msgstr "Ok<4F>nt element %s"
|
||||
|
||||
#. someone is on crack
|
||||
#: src/window.c:2852
|
||||
#, c-format
|
||||
msgid "Window %s sets max width %d less than min width %d, disabling resize\n"
|
||||
msgstr ""
|
||||
"F<>nstret %s st<73>ller in st<73>rsta bredden %d mindre <20>n minsta bredden %d, "
|
||||
"st<73>nger av storleks<6B>ndring\n"
|
||||
|
||||
#. another cracksmoker
|
||||
#: src/window.c:2862
|
||||
#, c-format
|
||||
msgid ""
|
||||
"Window %s sets max height %d less than min height %d, disabling resize\n"
|
||||
msgstr ""
|
||||
"F<>nstret %s st<73>ller in st<73>rsta h<>jden %d mindre <20>n minsta h<>jden %d, st<73>nger "
|
||||
"av storleks<6B>ndring\n"
|
@@ -9,6 +9,8 @@ metacity_SOURCES= \
|
||||
core.h \
|
||||
display.c \
|
||||
display.h \
|
||||
effects.c \
|
||||
effects.h \
|
||||
errors.c \
|
||||
errors.h \
|
||||
eventqueue.c \
|
||||
@@ -19,6 +21,7 @@ metacity_SOURCES= \
|
||||
frame.h \
|
||||
frames.c \
|
||||
frames.h \
|
||||
inlinepixbufs.h \
|
||||
keybindings.c \
|
||||
keybindings.h \
|
||||
main.c \
|
||||
@@ -33,6 +36,8 @@ metacity_SOURCES= \
|
||||
session.h \
|
||||
stack.c \
|
||||
stack.h \
|
||||
tabpopup.c \
|
||||
tabpopup.h \
|
||||
ui.c \
|
||||
ui.h \
|
||||
util.c \
|
||||
@@ -45,3 +50,17 @@ metacity_SOURCES= \
|
||||
bin_PROGRAMS=metacity
|
||||
|
||||
metacity_LDADD= @METACITY_LIBS@
|
||||
|
||||
desktopfilesdir=$(datadir)/gnome/wm-properties
|
||||
desktopfiles_DATA=metacity.desktop
|
||||
|
||||
IMAGES=default_icon.png
|
||||
VARIABLES=default_icon_data $(srcdir)/default_icon.png
|
||||
|
||||
BUILT_SOURCES = inlinepixbufs.h
|
||||
CLEANFILES += inlinepixbufs.h
|
||||
|
||||
inlinepixbufs.h: $(IMAGES)
|
||||
$(GDK_PIXBUF_CSOURCE) --raw --build-list $(VARIABLES) >$(srcdir)/inlinepixbufs.h
|
||||
|
||||
EXTRA_DIST=$(desktopfiles_DATA) $(IMAGES)
|
||||
|
22
src/common.h
22
src/common.h
@@ -31,7 +31,7 @@ typedef enum
|
||||
META_FRAME_ALLOWS_DELETE = 1 << 0,
|
||||
META_FRAME_ALLOWS_MENU = 1 << 1,
|
||||
META_FRAME_ALLOWS_MINIMIZE = 1 << 2,
|
||||
META_FRAME_ALLOWS_MAXIMIZE = 1 << 3,
|
||||
META_FRAME_ALLOWS_MAXIMIZE = 1 << 3,
|
||||
META_FRAME_ALLOWS_VERTICAL_RESIZE = 1 << 4,
|
||||
META_FRAME_ALLOWS_HORIZONTAL_RESIZE = 1 << 5,
|
||||
META_FRAME_TRANSIENT = 1 << 6,
|
||||
@@ -67,9 +67,13 @@ typedef void (* MetaWindowMenuFunc) (MetaWindowMenu *menu,
|
||||
int workspace,
|
||||
gpointer data);
|
||||
|
||||
/* when changing this enum, there are various switch statements
|
||||
* you have to update
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
META_GRAB_OP_NONE,
|
||||
|
||||
/* Mouse ops */
|
||||
META_GRAB_OP_MOVING,
|
||||
META_GRAB_OP_RESIZING_SE,
|
||||
@@ -80,6 +84,7 @@ typedef enum
|
||||
META_GRAB_OP_RESIZING_NW,
|
||||
META_GRAB_OP_RESIZING_W,
|
||||
META_GRAB_OP_RESIZING_E,
|
||||
|
||||
/* Keyboard ops */
|
||||
META_GRAB_OP_KEYBOARD_MOVING,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN,
|
||||
@@ -87,9 +92,17 @@ typedef enum
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_N,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_W,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_E,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_SE,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_NE,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_SW,
|
||||
META_GRAB_OP_KEYBOARD_RESIZING_NW,
|
||||
|
||||
META_GRAB_OP_KEYBOARD_TABBING,
|
||||
|
||||
/* Frame button ops */
|
||||
META_GRAB_OP_CLICKING_MINIMIZE,
|
||||
META_GRAB_OP_CLICKING_MAXIMIZE,
|
||||
META_GRAB_OP_CLICKING_UNMAXIMIZE,
|
||||
META_GRAB_OP_CLICKING_DELETE,
|
||||
META_GRAB_OP_CLICKING_MENU
|
||||
} MetaGrabOp;
|
||||
@@ -109,6 +122,13 @@ typedef enum
|
||||
|
||||
} MetaCursor;
|
||||
|
||||
|
||||
/* should investigate changing these to whatever most apps use */
|
||||
#define META_ICON_WIDTH 32
|
||||
#define META_ICON_HEIGHT 32
|
||||
#define META_MINI_ICON_WIDTH 16
|
||||
#define META_MINI_ICON_HEIGHT 16
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
33
src/core.c
33
src/core.c
@@ -60,6 +60,22 @@ meta_core_get_frame_flags (Display *xdisplay,
|
||||
return meta_frame_get_flags (window->frame);
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_core_get_mini_icon (Display *xdisplay,
|
||||
Window frame_xwindow)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
MetaWindow *window;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
window = meta_display_lookup_x_window (display, frame_xwindow);
|
||||
|
||||
if (window == NULL || window->frame == NULL)
|
||||
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
|
||||
|
||||
return window->mini_icon;
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_queue_frame_resize (Display *xdisplay,
|
||||
Window frame_xwindow)
|
||||
@@ -91,8 +107,7 @@ meta_core_user_move (Display *xdisplay,
|
||||
if (window == NULL || window->frame == NULL)
|
||||
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
|
||||
|
||||
window->user_has_moved = TRUE;
|
||||
meta_window_move (window, x, y);
|
||||
meta_window_move (window, TRUE, x, y);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -111,8 +126,7 @@ meta_core_user_resize (Display *xdisplay,
|
||||
if (window == NULL || window->frame == NULL)
|
||||
meta_bug ("No such frame window 0x%lx!\n", frame_xwindow);
|
||||
|
||||
window->user_has_resized = TRUE;
|
||||
meta_window_resize_with_gravity (window, width, height, gravity);
|
||||
meta_window_resize_with_gravity (window, TRUE, width, height, gravity);
|
||||
}
|
||||
|
||||
void
|
||||
@@ -494,3 +508,14 @@ meta_core_set_screen_cursor (Display *xdisplay,
|
||||
|
||||
meta_screen_set_cursor (window->screen, cursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_core_increment_event_serial (Display *xdisplay)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
meta_display_increment_event_serial (display);
|
||||
}
|
||||
|
||||
|
@@ -36,6 +36,9 @@ void meta_core_get_frame_size (Display *xdisplay,
|
||||
MetaFrameFlags meta_core_get_frame_flags (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
GdkPixbuf* meta_core_get_mini_icon (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
void meta_core_queue_frame_resize (Display *xdisplay,
|
||||
Window frame_xwindow);
|
||||
|
||||
@@ -124,6 +127,12 @@ void meta_core_set_screen_cursor (Display *xdisplay,
|
||||
Window frame_on_screen,
|
||||
MetaCursor cursor);
|
||||
|
||||
/* Used because we ignore EnterNotify when a window is unmapped that
|
||||
* really shouldn't cause focus changes, by comparing the event serial
|
||||
* of the EnterNotify and the UnmapNotify.
|
||||
*/
|
||||
void meta_core_increment_event_serial (Display *display);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
BIN
src/default_icon.png
Normal file
BIN
src/default_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 424 B |
224
src/display.c
224
src/display.c
@@ -68,15 +68,15 @@ unsigned_long_hash (gconstpointer v)
|
||||
}
|
||||
|
||||
static int
|
||||
set_string_hint (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom atom,
|
||||
const char *val)
|
||||
set_utf8_string_hint (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
Atom atom,
|
||||
const char *val)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XChangeProperty (display->xdisplay,
|
||||
xwindow, atom,
|
||||
XA_STRING,
|
||||
display->atom_utf8_string,
|
||||
8, PropModeReplace, (guchar*) val, strlen (val) + 1);
|
||||
return meta_error_trap_pop (display);
|
||||
}
|
||||
@@ -112,7 +112,7 @@ meta_display_open (const char *name)
|
||||
"WM_WINDOW_ROLE",
|
||||
"_NET_CURRENT_DESKTOP",
|
||||
"_NET_SUPPORTING_WM_CHECK",
|
||||
"_NET_WM_SUPPORTED",
|
||||
"_NET_SUPPORTED",
|
||||
"_NET_WM_WINDOW_TYPE",
|
||||
"_NET_WM_WINDOW_TYPE_DESKTOP",
|
||||
"_NET_WM_WINDOW_TYPE_DOCK",
|
||||
@@ -130,7 +130,13 @@ meta_display_open (const char *name)
|
||||
"_WIN_PROTOCOLS",
|
||||
"_WIN_SUPPORTING_WM_CHECK",
|
||||
"_NET_WM_ICON_NAME",
|
||||
"_NET_WM_ICON"
|
||||
"_NET_WM_ICON",
|
||||
"_NET_WM_ICON_GEOMETRY",
|
||||
"UTF8_STRING",
|
||||
"WM_ICON_SIZE",
|
||||
"_KWM_WIN_ICON",
|
||||
"_NET_WM_MOVERESIZE",
|
||||
"_NET_ACTIVE_WINDOW"
|
||||
};
|
||||
Atom atoms[G_N_ELEMENTS(atom_names)];
|
||||
|
||||
@@ -193,7 +199,7 @@ meta_display_open (const char *name)
|
||||
display->atom_wm_window_role = atoms[16];
|
||||
display->atom_net_current_desktop = atoms[17];
|
||||
display->atom_net_supporting_wm_check = atoms[18];
|
||||
display->atom_net_wm_supported = atoms[19];
|
||||
display->atom_net_supported = atoms[19];
|
||||
display->atom_net_wm_window_type = atoms[20];
|
||||
display->atom_net_wm_window_type_desktop = atoms[21];
|
||||
display->atom_net_wm_window_type_dock = atoms[22];
|
||||
@@ -212,6 +218,12 @@ meta_display_open (const char *name)
|
||||
display->atom_win_supporting_wm_check = atoms[35];
|
||||
display->atom_net_wm_icon_name = atoms[36];
|
||||
display->atom_net_wm_icon = atoms[37];
|
||||
display->atom_net_wm_icon_geometry = atoms[38];
|
||||
display->atom_utf8_string = atoms[39];
|
||||
display->atom_wm_icon_size = atoms[40];
|
||||
display->atom_kwm_win_icon = atoms[41];
|
||||
display->atom_net_wm_moveresize = atoms[42];
|
||||
display->atom_net_active_window = atoms[43];
|
||||
|
||||
/* Offscreen unmapped window used for _NET_SUPPORTING_WM_CHECK,
|
||||
* created in screen_new
|
||||
@@ -278,13 +290,15 @@ meta_display_open (const char *name)
|
||||
display->last_button_num = 0;
|
||||
display->is_double_click = FALSE;
|
||||
|
||||
display->last_ignored_unmap_serial = 0;
|
||||
|
||||
display->grab_op = META_GRAB_OP_NONE;
|
||||
display->grab_window = NULL;
|
||||
|
||||
set_string_hint (display,
|
||||
display->leader_window,
|
||||
display->atom_net_wm_name,
|
||||
"Metacity");
|
||||
set_utf8_string_hint (display,
|
||||
display->leader_window,
|
||||
display->atom_net_wm_name,
|
||||
"Metacity");
|
||||
|
||||
{
|
||||
/* The legacy GNOME hint is to set a cardinal which is the window
|
||||
@@ -588,6 +602,11 @@ grab_op_is_keyboard (MetaGrabOp op)
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_N:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_W:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_E:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NE:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_SW:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_NW:
|
||||
case META_GRAB_OP_KEYBOARD_TABBING:
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
@@ -629,6 +648,16 @@ event_callback (XEvent *event,
|
||||
display->last_button_xwindow = event->xbutton.window;
|
||||
display->last_button_time = event->xbutton.time;
|
||||
}
|
||||
else if (event->type == UnmapNotify)
|
||||
{
|
||||
if (meta_ui_window_should_not_cause_focus (display->xdisplay,
|
||||
event->xunmap.window))
|
||||
{
|
||||
display->last_ignored_unmap_serial = event->xany.serial;
|
||||
meta_verbose ("Will not focus on EnterNotify with serial %lu\n",
|
||||
display->last_ignored_unmap_serial);
|
||||
}
|
||||
}
|
||||
|
||||
modified = event_get_modified_window (display, event);
|
||||
|
||||
@@ -660,7 +689,7 @@ event_callback (XEvent *event,
|
||||
display->grab_window->desc);
|
||||
meta_display_end_grab_op (display,
|
||||
event->xbutton.time);
|
||||
}
|
||||
}
|
||||
else if (window && display->grab_op == META_GRAB_OP_NONE)
|
||||
{
|
||||
gboolean begin_move = FALSE;
|
||||
@@ -713,10 +742,19 @@ event_callback (XEvent *event,
|
||||
break;
|
||||
case EnterNotify:
|
||||
/* do this even if window->has_focus to avoid races */
|
||||
if (window)
|
||||
meta_window_focus (window, event->xcrossing.time);
|
||||
if (window && event->xany.serial != display->last_ignored_unmap_serial)
|
||||
{
|
||||
meta_window_focus (window, event->xcrossing.time);
|
||||
if (window->type == META_WINDOW_DOCK)
|
||||
meta_window_raise (window);
|
||||
}
|
||||
break;
|
||||
case LeaveNotify:
|
||||
if (window)
|
||||
{
|
||||
if (window->type == META_WINDOW_DOCK)
|
||||
meta_window_lower (window);
|
||||
}
|
||||
break;
|
||||
case FocusIn:
|
||||
case FocusOut:
|
||||
@@ -869,27 +907,29 @@ event_callback (XEvent *event,
|
||||
screen = meta_display_screen_for_root (display,
|
||||
event->xclient.window);
|
||||
|
||||
if (screen &&
|
||||
event->xclient.message_type ==
|
||||
display->atom_net_current_desktop)
|
||||
if (screen)
|
||||
{
|
||||
int space;
|
||||
MetaWorkspace *workspace;
|
||||
if (event->xclient.message_type ==
|
||||
display->atom_net_current_desktop)
|
||||
{
|
||||
int space;
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
space = event->xclient.data.l[0];
|
||||
space = event->xclient.data.l[0];
|
||||
|
||||
meta_verbose ("Request to change current workspace to %d\n",
|
||||
space);
|
||||
meta_verbose ("Request to change current workspace to %d\n",
|
||||
space);
|
||||
|
||||
workspace =
|
||||
meta_display_get_workspace_by_screen_index (display,
|
||||
screen,
|
||||
space);
|
||||
workspace =
|
||||
meta_display_get_workspace_by_screen_index (display,
|
||||
screen,
|
||||
space);
|
||||
|
||||
if (workspace)
|
||||
meta_workspace_activate (workspace);
|
||||
else
|
||||
meta_verbose ("Don't know about workspace %d\n", space);
|
||||
if (workspace)
|
||||
meta_workspace_activate (workspace);
|
||||
else
|
||||
meta_verbose ("Don't know about workspace %d\n", space);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@@ -1236,6 +1276,7 @@ meta_spew_event (MetaDisplay *display,
|
||||
name = "MappingNotify";
|
||||
break;
|
||||
default:
|
||||
meta_verbose ("Unknown event type %d\n", event->xany.type);
|
||||
name = "Unknown event type";
|
||||
break;
|
||||
}
|
||||
@@ -1247,8 +1288,9 @@ meta_spew_event (MetaDisplay *display,
|
||||
else
|
||||
winname = g_strdup_printf ("0x%lx", event->xany.window);
|
||||
|
||||
meta_verbose ("%s on %s%s %s\n", name, winname,
|
||||
extra ? ":" : "", extra ? extra : "");
|
||||
meta_verbose ("%s on %s%s %s serial %lu\n", name, winname,
|
||||
extra ? ":" : "", extra ? extra : "",
|
||||
event->xany.serial);
|
||||
|
||||
g_free (winname);
|
||||
|
||||
@@ -1449,9 +1491,9 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
if (pointer_already_grabbed)
|
||||
display->grab_have_pointer = TRUE;
|
||||
|
||||
/* We XGrabPointer even if we already have an autograb,
|
||||
* just to set the cursor and event mask
|
||||
*/
|
||||
/* We XGrabPointer even if we already have an autograb,
|
||||
* just to set the cursor and event mask
|
||||
*/
|
||||
|
||||
cursor = xcursor_for_op (display, op);
|
||||
|
||||
@@ -1466,7 +1508,10 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
None,
|
||||
cursor,
|
||||
timestamp) == GrabSuccess)
|
||||
display->grab_have_pointer = TRUE;
|
||||
{
|
||||
display->grab_have_pointer = TRUE;
|
||||
meta_debug_spew ("Successful XGrabPointer()\n");
|
||||
}
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
XFreeCursor (display->xdisplay, cursor);
|
||||
@@ -1476,36 +1521,25 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
meta_verbose ("XGrabPointer() failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
switch (op)
|
||||
|
||||
if (grab_op_is_keyboard (op))
|
||||
{
|
||||
case META_GRAB_OP_KEYBOARD_MOVING:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_UNKNOWN:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_S:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_N:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_W:
|
||||
case META_GRAB_OP_KEYBOARD_RESIZING_E:
|
||||
if (meta_window_grab_all_keys (window))
|
||||
display->grab_have_keyboard = TRUE;
|
||||
|
||||
|
||||
if (!display->grab_have_keyboard)
|
||||
{
|
||||
meta_verbose ("XGrabKeyboard() failed\n");
|
||||
meta_verbose ("grabbing all keys failed\n");
|
||||
return FALSE;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
/* non-keyboard grab ops */
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
display->grab_op = op;
|
||||
display->grab_window = window;
|
||||
display->grab_button = button;
|
||||
display->grab_root_x = root_x;
|
||||
display->grab_root_y = root_y;
|
||||
display->grab_initial_window_pos = window->rect;
|
||||
display->grab_initial_window_pos = display->grab_window->rect;
|
||||
meta_window_get_position (display->grab_window,
|
||||
&display->grab_initial_window_pos.x,
|
||||
&display->grab_initial_window_pos.y);
|
||||
@@ -1515,6 +1549,10 @@ meta_display_begin_grab_op (MetaDisplay *display,
|
||||
|
||||
g_assert (display->grab_window != NULL);
|
||||
g_assert (display->grab_op != META_GRAB_OP_NONE);
|
||||
|
||||
/* Do this last, after everything is set up. */
|
||||
if (op == META_GRAB_OP_KEYBOARD_TABBING)
|
||||
meta_screen_ensure_tab_popup (window->screen);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
@@ -1525,6 +1563,12 @@ meta_display_end_grab_op (MetaDisplay *display,
|
||||
{
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return;
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_KEYBOARD_TABBING)
|
||||
{
|
||||
meta_ui_tab_popup_free (display->grab_window->screen->tab_popup);
|
||||
display->grab_window->screen->tab_popup = NULL;
|
||||
}
|
||||
|
||||
if (display->grab_have_pointer)
|
||||
XUngrabPointer (display->xdisplay, timestamp);
|
||||
@@ -1544,6 +1588,11 @@ meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
* and Alt + button3 for popping up window menu.
|
||||
*/
|
||||
meta_verbose ("Grabbing window buttons for 0x%lx\n", xwindow);
|
||||
|
||||
/* FIXME If we ignored errors here instead of spewing, we could
|
||||
* put one big error trap around the loop and avoid a bunch of
|
||||
* XSync()
|
||||
*/
|
||||
|
||||
{
|
||||
int i = 1;
|
||||
@@ -1558,11 +1607,10 @@ meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
PointerMotionMask | PointerMotionHintMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
False, None);
|
||||
XSync (display->xdisplay, False);
|
||||
result = meta_error_trap_pop (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_warning ("Failed to grab button %d with Mod1Mask for frame 0x%lx error code %d\n",
|
||||
meta_warning ("Failed to grab button %d with Mod1Mask for window 0x%lx error code %d\n",
|
||||
i, xwindow, result);
|
||||
|
||||
|
||||
@@ -1578,11 +1626,10 @@ meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
PointerMotionMask | PointerMotionHintMask,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
False, None);
|
||||
XSync (display->xdisplay, False);
|
||||
result = meta_error_trap_pop (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_warning ("Failed to grab button %d with ControlMask for frame 0x%lx error code %d\n",
|
||||
meta_warning ("Failed to grab button %d with ControlMask for window 0x%lx error code %d\n",
|
||||
i, xwindow, result);
|
||||
}
|
||||
|
||||
@@ -1595,7 +1642,68 @@ void
|
||||
meta_display_ungrab_window_buttons (MetaDisplay *display,
|
||||
Window xwindow)
|
||||
{
|
||||
/* FIXME If we ignored errors here instead of spewing, we could
|
||||
* put one big error trap around the loop and avoid a bunch of
|
||||
* XSync()
|
||||
*/
|
||||
int i = 1;
|
||||
while (i < 4)
|
||||
{
|
||||
int result;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XUngrabButton (display->xdisplay, i, Mod1Mask, xwindow);
|
||||
result = meta_error_trap_pop (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_warning ("Failed to ungrab button %d with Mod1Mask for window 0x%lx error code %d\n",
|
||||
i, xwindow, result);
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XUngrabButton (display->xdisplay, i, ControlMask, xwindow);
|
||||
result = meta_error_trap_pop (display);
|
||||
|
||||
if (result != Success)
|
||||
meta_warning ("Failed to ungrab button %d with ControlMask for window 0x%lx error code %d\n",
|
||||
i, xwindow, result);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_increment_event_serial (MetaDisplay *display)
|
||||
{
|
||||
/* We just make some random X request */
|
||||
XDeleteProperty (display->xdisplay, display->leader_window,
|
||||
display->atom_motif_wm_hints);
|
||||
}
|
||||
|
||||
void
|
||||
meta_display_update_active_window_hint (MetaDisplay *display)
|
||||
{
|
||||
GSList *tmp;
|
||||
|
||||
unsigned long data[2];
|
||||
|
||||
if (display->focus_window)
|
||||
data[0] = display->focus_window->xwindow;
|
||||
else
|
||||
data[0] = None;
|
||||
data[1] = None;
|
||||
|
||||
tmp = display->screens;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
MetaScreen *screen = tmp->data;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XChangeProperty (display->xdisplay, screen->xroot,
|
||||
display->atom_net_active_window,
|
||||
XA_WINDOW,
|
||||
32, PropModeReplace, (guchar*) data, 2);
|
||||
meta_error_trap_pop (display);
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
@@ -76,7 +76,7 @@ struct _MetaDisplay
|
||||
Atom atom_wm_window_role;
|
||||
Atom atom_net_current_desktop;
|
||||
Atom atom_net_supporting_wm_check;
|
||||
Atom atom_net_wm_supported;
|
||||
Atom atom_net_supported;
|
||||
Atom atom_net_wm_window_type;
|
||||
Atom atom_net_wm_window_type_desktop;
|
||||
Atom atom_net_wm_window_type_dock;
|
||||
@@ -95,6 +95,12 @@ struct _MetaDisplay
|
||||
Atom atom_win_supporting_wm_check;
|
||||
Atom atom_net_wm_icon_name;
|
||||
Atom atom_net_wm_icon;
|
||||
Atom atom_net_wm_icon_geometry;
|
||||
Atom atom_utf8_string;
|
||||
Atom atom_wm_icon_size;
|
||||
Atom atom_kwm_win_icon;
|
||||
Atom atom_net_wm_moveresize;
|
||||
Atom atom_net_active_window;
|
||||
|
||||
/* This is the actual window from focus events,
|
||||
* not the one we last set
|
||||
@@ -119,6 +125,8 @@ struct _MetaDisplay
|
||||
Window last_button_xwindow;
|
||||
int last_button_num;
|
||||
guint is_double_click : 1;
|
||||
|
||||
unsigned long last_ignored_unmap_serial;
|
||||
|
||||
/* current window operation */
|
||||
MetaGrabOp grab_op;
|
||||
@@ -184,5 +192,9 @@ void meta_display_grab_window_buttons (MetaDisplay *display,
|
||||
void meta_display_ungrab_window_buttons (MetaDisplay *display,
|
||||
Window xwindow);
|
||||
|
||||
/* make a request to ensure the event serial has changed */
|
||||
void meta_display_increment_event_serial (MetaDisplay *display);
|
||||
|
||||
void meta_display_update_active_window_hint (MetaDisplay *display);
|
||||
|
||||
#endif
|
||||
|
259
src/effects.c
Normal file
259
src/effects.c
Normal file
@@ -0,0 +1,259 @@
|
||||
/* Metacity animation effects */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
||||
*
|
||||
* 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 "effects.h"
|
||||
#include "display.h"
|
||||
#include "ui.h"
|
||||
|
||||
typedef struct
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
double millisecs_duration;
|
||||
GTimeVal start_time;
|
||||
|
||||
gboolean first_time;
|
||||
|
||||
MetaRectangle start_rect;
|
||||
MetaRectangle end_rect;
|
||||
|
||||
/* rect to erase */
|
||||
MetaRectangle last_rect;
|
||||
|
||||
/* used instead of the global flag, since
|
||||
* we don't want to change midstream.
|
||||
*/
|
||||
gboolean use_opaque;
|
||||
|
||||
/* For wireframe */
|
||||
GC gc;
|
||||
|
||||
/* For opaque */
|
||||
MetaImageWindow *image_window;
|
||||
GdkPixbuf *orig_pixbuf;
|
||||
|
||||
} BoxAnimationContext;
|
||||
|
||||
static gboolean
|
||||
effects_draw_box_animation_timeout (BoxAnimationContext *context)
|
||||
{
|
||||
double elapsed;
|
||||
GTimeVal current_time;
|
||||
MetaRectangle draw_rect;
|
||||
double fraction;
|
||||
|
||||
if (!context->first_time)
|
||||
{
|
||||
if (!context->use_opaque)
|
||||
{
|
||||
/* Restore the previously drawn background */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
context->last_rect.x, context->last_rect.y,
|
||||
context->last_rect.width, context->last_rect.height);
|
||||
}
|
||||
}
|
||||
|
||||
context->first_time = FALSE;
|
||||
|
||||
g_get_current_time (¤t_time);
|
||||
|
||||
/* We use milliseconds for all times */
|
||||
elapsed =
|
||||
((((double)current_time.tv_sec - context->start_time.tv_sec) * G_USEC_PER_SEC +
|
||||
(current_time.tv_usec - context->start_time.tv_usec))) / 1000.0;
|
||||
|
||||
if (elapsed < 0)
|
||||
{
|
||||
/* Probably the system clock was set backwards? */
|
||||
meta_warning ("System clock seemed to go backwards?\n");
|
||||
elapsed = G_MAXDOUBLE; /* definitely done. */
|
||||
}
|
||||
|
||||
if (elapsed > context->millisecs_duration)
|
||||
{
|
||||
/* All done */
|
||||
if (context->use_opaque)
|
||||
{
|
||||
g_object_unref (G_OBJECT (context->orig_pixbuf));
|
||||
meta_image_window_free (context->image_window);
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_display_ungrab (context->screen->display);
|
||||
meta_ui_pop_delay_exposes (context->screen->ui);
|
||||
XFreeGC (context->screen->display->xdisplay,
|
||||
context->gc);
|
||||
}
|
||||
|
||||
g_free (context);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (context->millisecs_duration > 0.0);
|
||||
fraction = elapsed / context->millisecs_duration;
|
||||
|
||||
draw_rect = context->start_rect;
|
||||
|
||||
/* Now add a delta proportional to elapsed time. */
|
||||
draw_rect.x += (context->end_rect.x - context->start_rect.x) * fraction;
|
||||
draw_rect.y += (context->end_rect.y - context->start_rect.y) * fraction;
|
||||
draw_rect.width += (context->end_rect.width - context->start_rect.width) * fraction;
|
||||
draw_rect.height += (context->end_rect.height - context->start_rect.height) * fraction;
|
||||
|
||||
/* don't confuse X or gdk-pixbuf with bogus rectangles */
|
||||
if (draw_rect.width < 1)
|
||||
draw_rect.width = 1;
|
||||
if (draw_rect.height < 1)
|
||||
draw_rect.height = 1;
|
||||
|
||||
context->last_rect = draw_rect;
|
||||
|
||||
if (context->use_opaque)
|
||||
{
|
||||
GdkPixbuf *scaled;
|
||||
|
||||
scaled = gdk_pixbuf_scale_simple (context->orig_pixbuf,
|
||||
draw_rect.width,
|
||||
draw_rect.height,
|
||||
GDK_INTERP_BILINEAR);
|
||||
meta_image_window_set_image (context->image_window,
|
||||
scaled);
|
||||
meta_image_window_set_position (context->image_window,
|
||||
draw_rect.x, draw_rect.y);
|
||||
g_object_unref (G_OBJECT (scaled));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Draw the rectangle */
|
||||
XDrawRectangle (context->screen->display->xdisplay,
|
||||
context->screen->xroot,
|
||||
context->gc,
|
||||
draw_rect.x, draw_rect.y,
|
||||
draw_rect.width, draw_rect.height);
|
||||
}
|
||||
|
||||
/* kick changes onto the server */
|
||||
XFlush (context->screen->display->xdisplay);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
/* I really don't want this to be a configuration option,
|
||||
* but I think the wireframe is sucky from a UI standpoint
|
||||
* (more confusing than opaque), but the opaque is maybe
|
||||
* too slow on some systems; so perhaps we could autodetect
|
||||
* system beefiness or someting, or have some global
|
||||
* "my system is slow" config option.
|
||||
*/
|
||||
static gboolean use_opaque_animations = FALSE;
|
||||
|
||||
void
|
||||
meta_effects_draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration)
|
||||
{
|
||||
BoxAnimationContext *context;
|
||||
|
||||
g_return_if_fail (seconds_duration > 0.0);
|
||||
|
||||
if (g_getenv ("METACITY_DEBUG_EFFECTS"))
|
||||
seconds_duration *= 10; /* slow things down */
|
||||
|
||||
/* Create the animation context */
|
||||
context = g_new0 (BoxAnimationContext, 1);
|
||||
|
||||
context->screen = screen;
|
||||
|
||||
context->millisecs_duration = seconds_duration * 1000.0;
|
||||
context->first_time = TRUE;
|
||||
context->start_rect = *initial_rect;
|
||||
context->end_rect = *destination_rect;
|
||||
|
||||
context->use_opaque = use_opaque_animations;
|
||||
|
||||
if (context->use_opaque)
|
||||
{
|
||||
GdkPixbuf *pix;
|
||||
|
||||
pix = meta_gdk_pixbuf_get_from_window (NULL,
|
||||
screen->xroot,
|
||||
initial_rect->x,
|
||||
initial_rect->y,
|
||||
0, 0,
|
||||
initial_rect->width,
|
||||
initial_rect->height);
|
||||
|
||||
if (pix == NULL)
|
||||
{
|
||||
/* Fall back to wireframe */
|
||||
context->use_opaque = FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
context->image_window = meta_image_window_new ();
|
||||
context->orig_pixbuf = pix;
|
||||
meta_image_window_set_position (context->image_window,
|
||||
initial_rect->x,
|
||||
initial_rect->y);
|
||||
meta_image_window_set_showing (context->image_window, TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
/* Not an else, so that fallback works */
|
||||
if (!context->use_opaque)
|
||||
{
|
||||
XGCValues gc_values;
|
||||
|
||||
gc_values.subwindow_mode = IncludeInferiors;
|
||||
gc_values.function = GXinvert;
|
||||
|
||||
context->gc = XCreateGC (screen->display->xdisplay,
|
||||
screen->xroot,
|
||||
GCSubwindowMode | GCFunction,
|
||||
&gc_values);
|
||||
|
||||
/* Grab the X server to avoid screen dirt */
|
||||
meta_display_grab (context->screen->display);
|
||||
meta_ui_push_delay_exposes (context->screen->ui);
|
||||
}
|
||||
|
||||
/* Do this only after we get the pixbuf from the server,
|
||||
* so that the animation doesn't get truncated.
|
||||
*/
|
||||
g_get_current_time (&context->start_time);
|
||||
|
||||
/* Add the timeout - a short one, could even use an idle,
|
||||
* but this is maybe more CPU-friendly.
|
||||
*/
|
||||
g_timeout_add (15,
|
||||
(GSourceFunc)effects_draw_box_animation_timeout,
|
||||
context);
|
||||
|
||||
/* kick changes onto the server */
|
||||
XFlush (context->screen->display->xdisplay);
|
||||
}
|
||||
|
||||
|
||||
|
36
src/effects.h
Normal file
36
src/effects.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/* Metacity animation effects */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Anders Carlsson, Havoc Pennington
|
||||
*
|
||||
* 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_EFFECTS_H
|
||||
#define META_EFFECTS_H
|
||||
|
||||
#include "util.h"
|
||||
#include "screen.h"
|
||||
|
||||
#define META_MINIMIZE_ANIMATION_LENGTH 0.5
|
||||
#define META_SHADE_ANIMATION_LENGTH 0.2
|
||||
|
||||
void meta_effects_draw_box_animation (MetaScreen *screen,
|
||||
MetaRectangle *initial_rect,
|
||||
MetaRectangle *destination_rect,
|
||||
double seconds_duration);
|
||||
|
||||
#endif /* META_EFFECTS_H */
|
112
src/errors.c
112
src/errors.c
@@ -22,14 +22,13 @@
|
||||
|
||||
#include "errors.h"
|
||||
#include <errno.h>
|
||||
#include <stdlib.h>
|
||||
#include <gdk/gdk.h>
|
||||
|
||||
typedef struct _ErrorTrap ErrorTrap;
|
||||
static int (* saved_gdk_error_handler) (Display *display,
|
||||
XErrorEvent *error);
|
||||
|
||||
struct _ErrorTrap
|
||||
{
|
||||
int error_code;
|
||||
};
|
||||
static int (* saved_gdk_io_error_handler) (Display *display);
|
||||
|
||||
static int x_error_handler (Display *display,
|
||||
XErrorEvent *error);
|
||||
@@ -38,104 +37,44 @@ static int x_io_error_handler (Display *display);
|
||||
void
|
||||
meta_errors_init (void)
|
||||
{
|
||||
XSetErrorHandler (x_error_handler);
|
||||
XSetIOErrorHandler (x_io_error_handler);
|
||||
saved_gdk_error_handler = XSetErrorHandler (x_error_handler);
|
||||
saved_gdk_io_error_handler = XSetIOErrorHandler (x_io_error_handler);
|
||||
}
|
||||
|
||||
void
|
||||
meta_error_trap_push (MetaDisplay *display)
|
||||
{
|
||||
ErrorTrap *et;
|
||||
|
||||
gdk_error_trap_push ();
|
||||
return;
|
||||
|
||||
/* below here is old method */
|
||||
et = g_new (ErrorTrap, 1);
|
||||
|
||||
et->error_code = Success;
|
||||
display->error_traps = g_slist_prepend (display->error_traps, et);
|
||||
}
|
||||
|
||||
int
|
||||
meta_error_trap_pop (MetaDisplay *display)
|
||||
{
|
||||
int result;
|
||||
ErrorTrap *et;
|
||||
GSList *next;
|
||||
|
||||
/* just use GDK trap */
|
||||
XSync (display->xdisplay, False);
|
||||
|
||||
return gdk_error_trap_pop ();
|
||||
/* below here is old method */
|
||||
|
||||
if (display->error_traps == NULL)
|
||||
meta_bug ("No error trap to pop\n");
|
||||
|
||||
XSync (display->xdisplay, False);
|
||||
|
||||
et = display->error_traps->data;
|
||||
|
||||
result = et->error_code;
|
||||
|
||||
next = display->error_traps->next;
|
||||
g_slist_free_1 (display->error_traps);
|
||||
display->error_traps = next;
|
||||
|
||||
g_free (et);
|
||||
|
||||
if (result != Success)
|
||||
{
|
||||
gchar buf[64];
|
||||
|
||||
XGetErrorText (display->xdisplay, result, buf, 63);
|
||||
|
||||
meta_verbose ("Popping error code %d (%s)\n",
|
||||
result, buf);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
static int
|
||||
x_error_handler (Display *xdisplay,
|
||||
XErrorEvent *error)
|
||||
{
|
||||
if (error->error_code)
|
||||
{
|
||||
MetaDisplay *display;
|
||||
|
||||
display = meta_display_for_x_display (xdisplay);
|
||||
|
||||
if (display == NULL)
|
||||
meta_bug ("Error received for unknown display?\n");
|
||||
|
||||
if (display->error_traps == NULL)
|
||||
{
|
||||
gchar buf[64];
|
||||
|
||||
XGetErrorText (xdisplay, error->error_code, buf, 63);
|
||||
|
||||
meta_bug ("Received an X Window System error without handling it.\n"
|
||||
"The error was '%s'.\n"
|
||||
" (Details: serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
}
|
||||
else
|
||||
{
|
||||
ErrorTrap *et;
|
||||
|
||||
et = display->error_traps->data;
|
||||
|
||||
et->error_code = error->error_code;
|
||||
}
|
||||
}
|
||||
int retval;
|
||||
gchar buf[64];
|
||||
|
||||
return 0;
|
||||
XGetErrorText (xdisplay, error->error_code, buf, 63);
|
||||
|
||||
meta_verbose ("X error: %s serial %ld error_code %d request_code %d minor_code %d)\n",
|
||||
buf,
|
||||
error->serial,
|
||||
error->error_code,
|
||||
error->request_code,
|
||||
error->minor_code);
|
||||
|
||||
retval = saved_gdk_error_handler (xdisplay, error);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -162,11 +101,8 @@ x_io_error_handler (Display *xdisplay)
|
||||
display->name);
|
||||
}
|
||||
|
||||
meta_display_close (display);
|
||||
/* Xlib would force an exit anyhow */
|
||||
exit (1);
|
||||
|
||||
/* I believe Xlib will force an exit after we return, which
|
||||
* seems sort of broken to me, but if true we should probably just
|
||||
* exit for ourselves. But for now I'm not doing it.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
27
src/frame.c
27
src/frame.c
@@ -56,6 +56,19 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->mapped = FALSE;
|
||||
|
||||
attrs.event_mask = EVENT_MASK;
|
||||
|
||||
meta_verbose ("Framing window %s: visual %s default, depth %d default depth %d\n",
|
||||
window->desc,
|
||||
XVisualIDFromVisual (window->xvisual) ==
|
||||
XVisualIDFromVisual (window->screen->default_xvisual) ?
|
||||
"is" : "is not",
|
||||
window->depth, window->screen->default_depth);
|
||||
|
||||
/* Default depth/visual handles clients with weird visuals; they can
|
||||
* always be children of the root depth/visual obviously, but
|
||||
* e.g. DRI games can't be children of a parent that has the same
|
||||
* visual as the client.
|
||||
*/
|
||||
|
||||
frame->xwindow = XCreateWindow (window->display->xdisplay,
|
||||
window->screen->xroot,
|
||||
@@ -64,9 +77,9 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
frame->rect.width,
|
||||
frame->rect.height,
|
||||
0,
|
||||
window->depth,
|
||||
InputOutput,
|
||||
window->xvisual,
|
||||
window->screen->default_depth,
|
||||
CopyFromParent,
|
||||
window->screen->default_xvisual,
|
||||
CWEventMask,
|
||||
&attrs);
|
||||
|
||||
@@ -90,15 +103,18 @@ meta_window_ensure_frame (MetaWindow *window)
|
||||
* we don't want to take that as a withdraw
|
||||
*/
|
||||
window->unmaps_pending += 1;
|
||||
/* window was reparented to this position */
|
||||
window->rect.x = 0;
|
||||
window->rect.y = 0;
|
||||
|
||||
XReparentWindow (window->display->xdisplay,
|
||||
window->xwindow,
|
||||
frame->xwindow,
|
||||
window->rect.x,
|
||||
window->rect.y);
|
||||
/* FIXME handle this error */
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
|
||||
/* stick frame to the window */
|
||||
window->frame = frame;
|
||||
|
||||
@@ -245,6 +261,9 @@ meta_frame_sync_to_window (MetaFrame *frame,
|
||||
gboolean need_move,
|
||||
gboolean need_resize)
|
||||
{
|
||||
if (!(need_move || need_resize))
|
||||
return;
|
||||
|
||||
meta_verbose ("Syncing frame geometry %d,%d %dx%d (SE: %d,%d)\n",
|
||||
frame->rect.x, frame->rect.y,
|
||||
frame->rect.width, frame->rect.height,
|
||||
|
312
src/frames.c
312
src/frames.c
@@ -241,8 +241,8 @@ meta_frames_class_init (MetaFramesClass *class)
|
||||
INT_PROPERTY ("right_inset", 6, _("Right inset"), _("Distance of buttons from right edge of frame"));
|
||||
INT_PROPERTY ("left_inset", 6, _("Left inset"), _("Distance of menu button from left edge of frame"));
|
||||
|
||||
INT_PROPERTY ("button_width", 15, _("Button width"), _("Width of buttons"));
|
||||
INT_PROPERTY ("button_height", 15, _("Button height"), _("Height of buttons"));
|
||||
INT_PROPERTY ("button_width", 17, _("Button width"), _("Width of buttons"));
|
||||
INT_PROPERTY ("button_height", 17, _("Button height"), _("Height of buttons"));
|
||||
|
||||
BORDER_PROPERTY ("button_border", _("Button border"), _("Border around buttons"));
|
||||
BORDER_PROPERTY ("inner_button_border", _("Inner button border"), _("Border around the icon inside buttons"));
|
||||
@@ -278,6 +278,8 @@ meta_frames_init (MetaFrames *frames)
|
||||
frames->frames = g_hash_table_new (unsigned_long_hash, unsigned_long_equal);
|
||||
|
||||
frames->tooltip_timeout = 0;
|
||||
|
||||
frames->expose_delay_count = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -379,7 +381,7 @@ meta_frames_style_set (GtkWidget *widget,
|
||||
/* left, right, top, bottom */
|
||||
static GtkBorder default_title_border = { 3, 4, 4, 3 };
|
||||
static GtkBorder default_text_border = { 2, 2, 2, 2 };
|
||||
static GtkBorder default_button_border = { 1, 1, 1, 1 };
|
||||
static GtkBorder default_button_border = { 0, 0, 1, 1 };
|
||||
static GtkBorder default_inner_button_border = {
|
||||
DEFAULT_INNER_BUTTON_BORDER,
|
||||
DEFAULT_INNER_BUTTON_BORDER,
|
||||
@@ -456,18 +458,22 @@ meta_frames_style_set (GtkWidget *widget,
|
||||
*(frames->props) = props;
|
||||
|
||||
{
|
||||
PangoFontMetrics metrics;
|
||||
PangoFontMetrics *metrics;
|
||||
PangoFont *font;
|
||||
PangoLanguage *lang;
|
||||
|
||||
font = pango_context_load_font (gtk_widget_get_pango_context (widget),
|
||||
widget->style->font_desc);
|
||||
lang = pango_context_get_language (gtk_widget_get_pango_context (widget));
|
||||
pango_font_get_metrics (font, lang, &metrics);
|
||||
metrics = pango_font_get_metrics (font, lang);
|
||||
|
||||
g_object_unref (G_OBJECT (font));
|
||||
|
||||
frames->text_height = PANGO_PIXELS (metrics.ascent + metrics.descent);
|
||||
frames->text_height =
|
||||
PANGO_PIXELS (pango_font_metrics_get_ascent (metrics) +
|
||||
pango_font_metrics_get_descent (metrics));
|
||||
|
||||
pango_font_metrics_unref (metrics);
|
||||
}
|
||||
|
||||
/* Queue a draw/resize on all frames */
|
||||
@@ -698,6 +704,7 @@ meta_frames_manage_window (MetaFrames *frames,
|
||||
|
||||
frame->xwindow = xwindow;
|
||||
frame->layout = NULL;
|
||||
frame->expose_delayed = FALSE;
|
||||
|
||||
meta_core_grab_buttons (gdk_display, frame->xwindow);
|
||||
|
||||
@@ -884,6 +891,9 @@ show_tip_now (MetaFrames *frames)
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
tiptext = _("Maximize Window");
|
||||
break;
|
||||
case META_FRAME_CONTROL_UNMAXIMIZE:
|
||||
tiptext = _("Unmaximize Window");
|
||||
break;
|
||||
case META_FRAME_CONTROL_RESIZE_SE:
|
||||
break;
|
||||
case META_FRAME_CONTROL_RESIZE_S:
|
||||
@@ -1035,6 +1045,7 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
|
||||
if (event->button == 1 &&
|
||||
(control == META_FRAME_CONTROL_MAXIMIZE ||
|
||||
control == META_FRAME_CONTROL_UNMAXIMIZE ||
|
||||
control == META_FRAME_CONTROL_MINIMIZE ||
|
||||
control == META_FRAME_CONTROL_DELETE ||
|
||||
control == META_FRAME_CONTROL_MENU))
|
||||
@@ -1049,6 +1060,9 @@ meta_frames_button_press_event (GtkWidget *widget,
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
op = META_GRAB_OP_CLICKING_MAXIMIZE;
|
||||
break;
|
||||
case META_FRAME_CONTROL_UNMAXIMIZE:
|
||||
op = META_GRAB_OP_CLICKING_UNMAXIMIZE;
|
||||
break;
|
||||
case META_FRAME_CONTROL_DELETE:
|
||||
op = META_GRAB_OP_CLICKING_DELETE;
|
||||
break;
|
||||
@@ -1258,18 +1272,24 @@ meta_frames_button_release_event (GtkWidget *widget,
|
||||
if (point_in_control (frames, frame,
|
||||
META_FRAME_CONTROL_MAXIMIZE,
|
||||
event->x, event->y))
|
||||
{
|
||||
if (meta_core_get_frame_flags (gdk_display, frame->xwindow) &
|
||||
META_FRAME_MAXIMIZED)
|
||||
meta_core_unmaximize (gdk_display, frame->xwindow);
|
||||
else
|
||||
meta_core_maximize (gdk_display, frame->xwindow);
|
||||
}
|
||||
meta_core_maximize (gdk_display, frame->xwindow);
|
||||
|
||||
redraw_control (frames, frame,
|
||||
META_FRAME_CONTROL_MAXIMIZE);
|
||||
end_grab = TRUE;
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
if (point_in_control (frames, frame,
|
||||
META_FRAME_CONTROL_UNMAXIMIZE,
|
||||
event->x, event->y))
|
||||
meta_core_unmaximize (gdk_display, frame->xwindow);
|
||||
|
||||
redraw_control (frames, frame,
|
||||
META_FRAME_CONTROL_MAXIMIZE);
|
||||
end_grab = TRUE;
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
if (point_in_control (frames, frame,
|
||||
META_FRAME_CONTROL_DELETE,
|
||||
@@ -1320,6 +1340,7 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
case META_GRAB_OP_CLICKING_DELETE:
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
break;
|
||||
|
||||
case META_GRAB_OP_NONE:
|
||||
@@ -1348,6 +1369,8 @@ meta_frames_motion_notify_event (GtkWidget *widget,
|
||||
break;
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
break;
|
||||
case META_FRAME_CONTROL_UNMAXIMIZE:
|
||||
break;
|
||||
case META_FRAME_CONTROL_RESIZE_SE:
|
||||
cursor = META_CURSOR_SE_RESIZE;
|
||||
break;
|
||||
@@ -1406,75 +1429,112 @@ meta_frames_destroy_event (GtkWidget *widget,
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
#define THICK_LINE_WIDTH 3
|
||||
static void
|
||||
draw_mini_window (MetaFrames *frames,
|
||||
GdkDrawable *drawable,
|
||||
GdkGC *fg_gc,
|
||||
GdkGC *bg_gc,
|
||||
gboolean thin_title,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
GdkGCValues vals;
|
||||
|
||||
gdk_draw_rectangle (drawable,
|
||||
bg_gc,
|
||||
TRUE,
|
||||
x, y, width - 1, height - 1);
|
||||
|
||||
gdk_draw_rectangle (drawable,
|
||||
fg_gc,
|
||||
FALSE,
|
||||
x, y, width - 1, height - 1);
|
||||
|
||||
vals.line_width = thin_title ? THICK_LINE_WIDTH - 1 : THICK_LINE_WIDTH;
|
||||
gdk_gc_set_values (fg_gc,
|
||||
&vals,
|
||||
GDK_GC_LINE_WIDTH);
|
||||
|
||||
gdk_draw_line (drawable,
|
||||
fg_gc,
|
||||
x, y + 1, x + width, y + 1);
|
||||
|
||||
vals.line_width = 0;
|
||||
gdk_gc_set_values (fg_gc,
|
||||
&vals,
|
||||
GDK_GC_LINE_WIDTH);
|
||||
}
|
||||
|
||||
static void
|
||||
draw_control (MetaFrames *frames,
|
||||
GdkDrawable *drawable,
|
||||
GdkGC *override,
|
||||
GdkGC *fg_override,
|
||||
GdkGC *bg_override,
|
||||
MetaFrameControl control,
|
||||
int x, int y, int width, int height)
|
||||
{
|
||||
GtkWidget *widget;
|
||||
GdkGCValues vals;
|
||||
GdkGC *gc;
|
||||
GdkGC *fg_gc;
|
||||
GdkGC *bg_gc;
|
||||
|
||||
widget = GTK_WIDGET (frames);
|
||||
|
||||
#define THICK_LINE_WIDTH 3
|
||||
|
||||
gc = override ? override : widget->style->fg_gc[GTK_STATE_NORMAL];
|
||||
fg_gc = fg_override ? fg_override : widget->style->fg_gc[GTK_STATE_NORMAL];
|
||||
bg_gc = bg_override ? bg_override : widget->style->bg_gc[GTK_STATE_NORMAL];
|
||||
|
||||
switch (control)
|
||||
{
|
||||
case META_FRAME_CONTROL_DELETE:
|
||||
{
|
||||
gdk_draw_line (drawable,
|
||||
gc,
|
||||
fg_gc,
|
||||
x, y, x + width - 1, y + height - 1);
|
||||
|
||||
gdk_draw_line (drawable,
|
||||
gc,
|
||||
fg_gc,
|
||||
x, y + height - 1, x + width - 1, y);
|
||||
}
|
||||
break;
|
||||
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
{
|
||||
gdk_draw_rectangle (drawable,
|
||||
gc,
|
||||
FALSE,
|
||||
x, y, width - 1, height - 1);
|
||||
|
||||
vals.line_width = THICK_LINE_WIDTH;
|
||||
gdk_gc_set_values (gc,
|
||||
&vals,
|
||||
GDK_GC_LINE_WIDTH);
|
||||
|
||||
gdk_draw_line (drawable,
|
||||
gc,
|
||||
x, y + 1, x + width, y + 1);
|
||||
|
||||
vals.line_width = 0;
|
||||
gdk_gc_set_values (gc,
|
||||
&vals,
|
||||
GDK_GC_LINE_WIDTH);
|
||||
draw_mini_window (frames, drawable, fg_gc, bg_gc, FALSE,
|
||||
x, y, width, height);
|
||||
}
|
||||
break;
|
||||
|
||||
case META_FRAME_CONTROL_UNMAXIMIZE:
|
||||
{
|
||||
int w_delta = width * 0.3;
|
||||
int h_delta = height * 0.3;
|
||||
|
||||
w_delta = MAX (w_delta, 3);
|
||||
h_delta = MAX (h_delta, 3);
|
||||
|
||||
draw_mini_window (frames, drawable, fg_gc, bg_gc, TRUE,
|
||||
x, y, width - w_delta, height - h_delta);
|
||||
draw_mini_window (frames, drawable, fg_gc, bg_gc, TRUE,
|
||||
x + w_delta, y + h_delta,
|
||||
width - w_delta, height - h_delta);
|
||||
}
|
||||
break;
|
||||
|
||||
case META_FRAME_CONTROL_MINIMIZE:
|
||||
{
|
||||
|
||||
vals.line_width = THICK_LINE_WIDTH;
|
||||
gdk_gc_set_values (gc,
|
||||
gdk_gc_set_values (fg_gc,
|
||||
&vals,
|
||||
GDK_GC_LINE_WIDTH);
|
||||
|
||||
gdk_draw_line (drawable,
|
||||
gc,
|
||||
fg_gc,
|
||||
x, y + height - THICK_LINE_WIDTH + 1,
|
||||
x + width, y + height - THICK_LINE_WIDTH + 1);
|
||||
|
||||
vals.line_width = 0;
|
||||
gdk_gc_set_values (gc,
|
||||
gdk_gc_set_values (fg_gc,
|
||||
&vals,
|
||||
GDK_GC_LINE_WIDTH);
|
||||
}
|
||||
@@ -1483,8 +1543,8 @@ draw_control (MetaFrames *frames,
|
||||
default:
|
||||
break;
|
||||
}
|
||||
#undef THICK_LINE_WIDTH
|
||||
}
|
||||
#undef THICK_LINE_WIDTH
|
||||
|
||||
void
|
||||
meta_frames_get_pixmap_for_control (MetaFrames *frames,
|
||||
@@ -1496,7 +1556,7 @@ meta_frames_get_pixmap_for_control (MetaFrames *frames,
|
||||
GdkPixmap *pix;
|
||||
GdkBitmap *mask;
|
||||
GtkWidget *widget;
|
||||
GdkGC *mgc;
|
||||
GdkGC *mgc, *mgc_bg;
|
||||
GdkColor color;
|
||||
|
||||
widget = GTK_WIDGET (frames);
|
||||
@@ -1516,18 +1576,21 @@ meta_frames_get_pixmap_for_control (MetaFrames *frames,
|
||||
mask = gdk_pixmap_new (NULL, w, h, 1);
|
||||
|
||||
mgc = gdk_gc_new (mask);
|
||||
|
||||
mgc_bg = gdk_gc_new (mask);
|
||||
|
||||
color.pixel = 0;
|
||||
gdk_gc_set_foreground (mgc, &color);
|
||||
gdk_draw_rectangle (mask, mgc, TRUE, 0, 0, -1, -1);
|
||||
|
||||
gdk_gc_set_foreground (mgc_bg, &color);
|
||||
color.pixel = 1;
|
||||
gdk_gc_set_foreground (mgc, &color);
|
||||
draw_control (frames, mask, mgc, control, 0, 0, w, h);
|
||||
|
||||
gdk_draw_rectangle (mask, mgc_bg, TRUE, 0, 0, -1, -1);
|
||||
|
||||
draw_control (frames, mask, mgc, mgc_bg, control, 0, 0, w, h);
|
||||
|
||||
gdk_gc_unref (mgc);
|
||||
gdk_gc_unref (mgc_bg);
|
||||
|
||||
draw_control (frames, pix, NULL, control, 0, 0, w, h);
|
||||
draw_control (frames, pix, NULL, NULL, control, 0, 0, w, h);
|
||||
|
||||
*pixmapp = pix;
|
||||
*maskp = mask;
|
||||
@@ -1560,7 +1623,10 @@ draw_control_bg (MetaFrames *frames,
|
||||
break;
|
||||
case META_GRAB_OP_CLICKING_MAXIMIZE:
|
||||
draw = control == META_FRAME_CONTROL_MAXIMIZE;
|
||||
break;
|
||||
break;
|
||||
case META_GRAB_OP_CLICKING_UNMAXIMIZE:
|
||||
draw = control == META_FRAME_CONTROL_UNMAXIMIZE;
|
||||
break;
|
||||
case META_GRAB_OP_CLICKING_MINIMIZE:
|
||||
draw = control == META_FRAME_CONTROL_MINIMIZE;
|
||||
break;
|
||||
@@ -1601,6 +1667,13 @@ meta_frames_expose_event (GtkWidget *widget,
|
||||
if (frame == NULL)
|
||||
return FALSE;
|
||||
|
||||
if (frames->expose_delay_count > 0)
|
||||
{
|
||||
/* Redraw this entire frame later */
|
||||
frame->expose_delayed = TRUE;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
meta_frames_calc_geometry (frames, frame, &fgeom);
|
||||
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
|
||||
meta_core_get_frame_size (gdk_display, frame->xwindow, &width, &height);
|
||||
@@ -1671,11 +1744,78 @@ meta_frames_expose_event (GtkWidget *widget,
|
||||
|
||||
if (frame->layout)
|
||||
{
|
||||
PangoRectangle layout_rect;
|
||||
int x, y, icon_x, icon_y;
|
||||
GdkPixbuf *icon;
|
||||
int icon_w, icon_h;
|
||||
int area_w, area_h;
|
||||
|
||||
#define ICON_TEXT_SPACING 2
|
||||
|
||||
icon = meta_core_get_mini_icon (gdk_display,
|
||||
frame->xwindow);
|
||||
|
||||
icon_w = gdk_pixbuf_get_width (icon);
|
||||
icon_h = gdk_pixbuf_get_height (icon);
|
||||
|
||||
pango_layout_get_pixel_extents (frame->layout,
|
||||
NULL,
|
||||
&layout_rect);
|
||||
|
||||
/* corner of whole title area */
|
||||
x = fgeom.title_rect.x + frames->props->text_border.left;
|
||||
y = fgeom.title_rect.y + frames->props->text_border.top;
|
||||
|
||||
area_w = fgeom.title_rect.width -
|
||||
frames->props->text_border.left -
|
||||
frames->props->text_border.right;
|
||||
|
||||
area_h = fgeom.title_rect.height -
|
||||
frames->props->text_border.top -
|
||||
frames->props->text_border.bottom;
|
||||
|
||||
/* center icon vertically */
|
||||
icon_y = y + MAX ((area_h - icon_h) / 2, 0);
|
||||
/* center text vertically */
|
||||
y = y + MAX ((area_h - layout_rect.height) / 2, 0);
|
||||
|
||||
/* Center icon + text combo */
|
||||
icon_x = x + MAX ((area_w - layout_rect.width - icon_w - ICON_TEXT_SPACING) / 2, 0);
|
||||
x = icon_x + icon_w + ICON_TEXT_SPACING;
|
||||
|
||||
gdk_gc_set_clip_rectangle (layout_gc, &clip);
|
||||
|
||||
{
|
||||
/* grumble, render_to_drawable_alpha does not accept a clip
|
||||
* mask, so we have to go through some BS
|
||||
*/
|
||||
GdkRectangle pixbuf_rect;
|
||||
GdkRectangle draw_rect;
|
||||
|
||||
pixbuf_rect.x = icon_x;
|
||||
pixbuf_rect.y = icon_y;
|
||||
pixbuf_rect.width = icon_w;
|
||||
pixbuf_rect.height = icon_h;
|
||||
|
||||
if (gdk_rectangle_intersect (&clip, &pixbuf_rect, &draw_rect))
|
||||
{
|
||||
gdk_pixbuf_render_to_drawable_alpha (icon,
|
||||
frame->window,
|
||||
draw_rect.x - pixbuf_rect.x,
|
||||
draw_rect.y - pixbuf_rect.y,
|
||||
draw_rect.x, draw_rect.y,
|
||||
draw_rect.width,
|
||||
draw_rect.height,
|
||||
GDK_PIXBUF_ALPHA_FULL,
|
||||
128,
|
||||
GDK_RGB_DITHER_NORMAL,
|
||||
0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
gdk_draw_layout (frame->window,
|
||||
layout_gc,
|
||||
fgeom.title_rect.x + frames->props->text_border.left,
|
||||
fgeom.title_rect.y + frames->props->text_border.top,
|
||||
x, y,
|
||||
frame->layout);
|
||||
gdk_gc_set_clip_rectangle (layout_gc, NULL);
|
||||
}
|
||||
@@ -1688,7 +1828,7 @@ meta_frames_expose_event (GtkWidget *widget,
|
||||
draw_control_bg (frames, frame, META_FRAME_CONTROL_DELETE, &fgeom);
|
||||
|
||||
draw_control (frames, frame->window,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
META_FRAME_CONTROL_DELETE,
|
||||
fgeom.close_rect.x + inner.left,
|
||||
fgeom.close_rect.y + inner.top,
|
||||
@@ -1698,11 +1838,18 @@ meta_frames_expose_event (GtkWidget *widget,
|
||||
|
||||
if (fgeom.max_rect.width > 0 && fgeom.max_rect.height > 0)
|
||||
{
|
||||
draw_control_bg (frames, frame, META_FRAME_CONTROL_MAXIMIZE, &fgeom);
|
||||
MetaFrameControl ctrl;
|
||||
|
||||
if (flags & META_FRAME_MAXIMIZED)
|
||||
ctrl = META_FRAME_CONTROL_UNMAXIMIZE;
|
||||
else
|
||||
ctrl = META_FRAME_CONTROL_MAXIMIZE;
|
||||
|
||||
draw_control_bg (frames, frame, ctrl, &fgeom);
|
||||
|
||||
draw_control (frames, frame->window,
|
||||
NULL,
|
||||
META_FRAME_CONTROL_MAXIMIZE,
|
||||
NULL, NULL,
|
||||
ctrl,
|
||||
fgeom.max_rect.x + inner.left,
|
||||
fgeom.max_rect.y + inner.top,
|
||||
fgeom.max_rect.width - inner.left - inner.right,
|
||||
@@ -1714,7 +1861,7 @@ meta_frames_expose_event (GtkWidget *widget,
|
||||
draw_control_bg (frames, frame, META_FRAME_CONTROL_MINIMIZE, &fgeom);
|
||||
|
||||
draw_control (frames, frame->window,
|
||||
NULL,
|
||||
NULL, NULL,
|
||||
META_FRAME_CONTROL_MINIMIZE,
|
||||
fgeom.min_rect.x + inner.left,
|
||||
fgeom.min_rect.y + inner.top,
|
||||
@@ -1983,6 +2130,7 @@ control_rect (MetaFrameControl control,
|
||||
rect = &fgeom->min_rect;
|
||||
break;
|
||||
case META_FRAME_CONTROL_MAXIMIZE:
|
||||
case META_FRAME_CONTROL_UNMAXIMIZE:
|
||||
rect = &fgeom->max_rect;
|
||||
break;
|
||||
case META_FRAME_CONTROL_RESIZE_SE:
|
||||
@@ -2041,17 +2189,22 @@ get_control (MetaFrames *frames,
|
||||
if (POINT_IN_RECT (x, y, fgeom.min_rect))
|
||||
return META_FRAME_CONTROL_MINIMIZE;
|
||||
|
||||
if (POINT_IN_RECT (x, y, fgeom.max_rect))
|
||||
return META_FRAME_CONTROL_MAXIMIZE;
|
||||
|
||||
if (POINT_IN_RECT (x, y, fgeom.menu_rect))
|
||||
return META_FRAME_CONTROL_MENU;
|
||||
|
||||
if (POINT_IN_RECT (x, y, fgeom.title_rect))
|
||||
return META_FRAME_CONTROL_TITLE;
|
||||
|
||||
|
||||
flags = meta_core_get_frame_flags (gdk_display, frame->xwindow);
|
||||
|
||||
if (POINT_IN_RECT (x, y, fgeom.max_rect))
|
||||
{
|
||||
if (flags & META_FRAME_MAXIMIZED)
|
||||
return META_FRAME_CONTROL_UNMAXIMIZE;
|
||||
else
|
||||
return META_FRAME_CONTROL_MAXIMIZE;
|
||||
}
|
||||
|
||||
has_vert = (flags & META_FRAME_ALLOWS_VERTICAL_RESIZE) != 0;
|
||||
has_horiz = (flags & META_FRAME_ALLOWS_HORIZONTAL_RESIZE) != 0;
|
||||
|
||||
@@ -2096,3 +2249,40 @@ get_control (MetaFrames *frames,
|
||||
|
||||
return META_FRAME_CONTROL_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
meta_frames_push_delay_exposes (MetaFrames *frames)
|
||||
{
|
||||
frames->expose_delay_count += 1;
|
||||
}
|
||||
|
||||
static void
|
||||
queue_pending_exposes_func (gpointer key, gpointer value, gpointer data)
|
||||
{
|
||||
MetaUIFrame *frame;
|
||||
MetaFrames *frames;
|
||||
|
||||
frames = META_FRAMES (data);
|
||||
frame = value;
|
||||
|
||||
if (frame->expose_delayed)
|
||||
{
|
||||
gdk_window_invalidate_rect (frame->window, NULL, FALSE);
|
||||
frame->expose_delayed = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_frames_pop_delay_exposes (MetaFrames *frames)
|
||||
{
|
||||
g_return_if_fail (frames->expose_delay_count > 0);
|
||||
|
||||
frames->expose_delay_count -= 1;
|
||||
|
||||
if (frames->expose_delay_count == 0)
|
||||
{
|
||||
g_hash_table_foreach (frames->frames,
|
||||
queue_pending_exposes_func,
|
||||
frames);
|
||||
}
|
||||
}
|
||||
|
@@ -34,6 +34,7 @@ typedef enum
|
||||
META_FRAME_CONTROL_MENU,
|
||||
META_FRAME_CONTROL_MINIMIZE,
|
||||
META_FRAME_CONTROL_MAXIMIZE,
|
||||
META_FRAME_CONTROL_UNMAXIMIZE,
|
||||
META_FRAME_CONTROL_RESIZE_SE,
|
||||
META_FRAME_CONTROL_RESIZE_S,
|
||||
META_FRAME_CONTROL_RESIZE_SW,
|
||||
@@ -66,6 +67,7 @@ struct _MetaUIFrame
|
||||
Window xwindow;
|
||||
GdkWindow *window;
|
||||
PangoLayout *layout;
|
||||
guint expose_delayed : 1;
|
||||
};
|
||||
|
||||
struct _MetaFrames
|
||||
@@ -81,6 +83,8 @@ struct _MetaFrames
|
||||
|
||||
guint tooltip_timeout;
|
||||
MetaUIFrame *last_motion_frame;
|
||||
|
||||
int expose_delay_count;
|
||||
};
|
||||
|
||||
struct _MetaFramesClass
|
||||
@@ -121,4 +125,7 @@ void meta_frames_notify_menu_hide (MetaFrames *frames);
|
||||
|
||||
Window meta_frames_get_moving_frame (MetaFrames *frames);
|
||||
|
||||
void meta_frames_push_delay_exposes (MetaFrames *frames);
|
||||
void meta_frames_pop_delay_exposes (MetaFrames *frames);
|
||||
|
||||
#endif
|
||||
|
@@ -62,9 +62,19 @@ static void handle_workspace_left (MetaDisplay *display,
|
||||
XEvent *event,
|
||||
gpointer data);
|
||||
static void handle_workspace_right (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
gpointer data);
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
gpointer data);
|
||||
|
||||
static gboolean process_keyboard_move_grab (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
KeySym keysym);
|
||||
|
||||
static gboolean process_tab_grab (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
KeySym keysym);
|
||||
|
||||
typedef struct _MetaKeyBinding MetaKeyBinding;
|
||||
|
||||
@@ -78,7 +88,8 @@ struct _MetaKeyBinding
|
||||
int keycode;
|
||||
};
|
||||
|
||||
#define INTERESTING_MODIFIERS (ShiftMask | ControlMask | Mod1Mask)
|
||||
#define IGNORED_MODIFIERS (LockMask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask)
|
||||
#define INTERESTING_MODIFIERS (~IGNORED_MODIFIERS)
|
||||
|
||||
static MetaKeyBinding screen_bindings[] = {
|
||||
{ XK_F1, Mod1Mask, KeyPress, handle_activate_workspace, GINT_TO_POINTER (0), 0 },
|
||||
@@ -134,6 +145,88 @@ meta_display_init_keys (MetaDisplay *display)
|
||||
init_bindings (display, window_bindings);
|
||||
}
|
||||
|
||||
/* Grab/ungrab, ignoring all annoying modifiers like NumLock etc. */
|
||||
static void
|
||||
meta_change_keygrab (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
gboolean grab,
|
||||
int keysym,
|
||||
int keycode,
|
||||
int modmask)
|
||||
{
|
||||
int result;
|
||||
int ignored_mask;
|
||||
|
||||
/* Grab keycode/modmask, together with
|
||||
* all combinations of IGNORED_MODIFIERS.
|
||||
* X provides no better way to do this.
|
||||
*/
|
||||
|
||||
/* modmask can't contain any non-interesting modifiers */
|
||||
g_return_if_fail ((modmask & INTERESTING_MODIFIERS) == modmask);
|
||||
|
||||
ignored_mask = 0;
|
||||
while (ignored_mask < IGNORED_MODIFIERS)
|
||||
{
|
||||
if (ignored_mask & INTERESTING_MODIFIERS)
|
||||
{
|
||||
/* Not a combination of IGNORED_MODIFIERS
|
||||
* (it contains some non-ignored modifiers)
|
||||
*/
|
||||
++ignored_mask;
|
||||
continue;
|
||||
}
|
||||
|
||||
meta_error_trap_push (display);
|
||||
if (grab)
|
||||
XGrabKey (display->xdisplay, keycode,
|
||||
modmask | ignored_mask,
|
||||
xwindow,
|
||||
True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
else
|
||||
XUngrabKey (display->xdisplay, keycode,
|
||||
modmask | ignored_mask,
|
||||
xwindow);
|
||||
|
||||
result = meta_error_trap_pop (display);
|
||||
|
||||
if (grab && result != Success)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = XKeysymToString (keysym);
|
||||
if (name == NULL)
|
||||
name = "(unknown)";
|
||||
|
||||
if (result == BadAccess)
|
||||
meta_warning (_("Some other program is already using the key %s with modifiers %x as a binding\n"), name, modmask | ignored_mask);
|
||||
}
|
||||
|
||||
++ignored_mask;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
meta_grab_key (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
int keysym,
|
||||
int keycode,
|
||||
int modmask)
|
||||
{
|
||||
meta_change_keygrab (display, xwindow, TRUE, keysym, keycode, modmask);
|
||||
}
|
||||
|
||||
static void
|
||||
meta_ungrab_key (MetaDisplay *display,
|
||||
Window xwindow,
|
||||
int keysym,
|
||||
int keycode,
|
||||
int modmask)
|
||||
{
|
||||
meta_change_keygrab (display, xwindow, FALSE, keysym, keycode, modmask);
|
||||
}
|
||||
|
||||
static void
|
||||
grab_keys (MetaKeyBinding *bindings,
|
||||
MetaDisplay *display,
|
||||
@@ -146,24 +239,10 @@ grab_keys (MetaKeyBinding *bindings,
|
||||
{
|
||||
if (bindings[i].keycode != 0)
|
||||
{
|
||||
int result;
|
||||
|
||||
meta_error_trap_push (display);
|
||||
XGrabKey (display->xdisplay, bindings[i].keycode,
|
||||
bindings[i].mask, xwindow, True,
|
||||
GrabModeAsync, GrabModeAsync);
|
||||
result = meta_error_trap_pop (display);
|
||||
if (result != Success)
|
||||
{
|
||||
const char *name;
|
||||
|
||||
name = XKeysymToString (bindings[i].keysym);
|
||||
if (name == NULL)
|
||||
name = "(unknown)";
|
||||
|
||||
if (result == BadAccess)
|
||||
meta_warning (_("Some other program is already using the key %s as a binding\n"), name);
|
||||
}
|
||||
meta_grab_key (display, xwindow,
|
||||
bindings[i].keysym,
|
||||
bindings[i].keycode,
|
||||
bindings[i].mask);
|
||||
}
|
||||
|
||||
++i;
|
||||
@@ -182,10 +261,10 @@ ungrab_keys (MetaKeyBinding *bindings,
|
||||
{
|
||||
if (bindings[i].keycode != 0)
|
||||
{
|
||||
meta_error_trap_push (display);
|
||||
XUngrabKey (display->xdisplay, bindings[i].keycode,
|
||||
bindings[i].mask, xwindow);
|
||||
meta_error_trap_pop (display);
|
||||
meta_ungrab_key (display, xwindow,
|
||||
bindings[i].keysym,
|
||||
bindings[i].keycode,
|
||||
bindings[i].mask);
|
||||
}
|
||||
|
||||
++i;
|
||||
@@ -281,10 +360,30 @@ meta_window_grab_all_keys (MetaWindow *window)
|
||||
}
|
||||
else
|
||||
{
|
||||
window->keys_grabbed = FALSE;
|
||||
window->all_keys_grabbed = TRUE;
|
||||
window->grab_on_frame = window->frame != NULL;
|
||||
return TRUE;
|
||||
/* Also grab the keyboard, so we get key releases and all key
|
||||
* presses
|
||||
*/
|
||||
meta_error_trap_push (window->display);
|
||||
/* FIXME CurrentTime bogus */
|
||||
XGrabKeyboard (window->display->xdisplay,
|
||||
grabwindow, True,
|
||||
GrabModeAsync, GrabModeAsync,
|
||||
CurrentTime);
|
||||
|
||||
result = meta_error_trap_pop (window->display);
|
||||
if (result != Success)
|
||||
{
|
||||
meta_verbose ("XGrabKeyboard() failed for window %s\n",
|
||||
window->desc);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
meta_verbose ("Grabbed all keys on window %s\n", window->desc);
|
||||
|
||||
window->keys_grabbed = FALSE;
|
||||
window->all_keys_grabbed = TRUE;
|
||||
window->grab_on_frame = window->frame != NULL;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -302,6 +401,8 @@ meta_window_ungrab_all_keys (MetaWindow *window)
|
||||
XUngrabKey (window->display->xdisplay,
|
||||
AnyKey, AnyModifier,
|
||||
grabwindow);
|
||||
/* FIXME CurrentTime bogus */
|
||||
XUngrabKeyboard (window->display->xdisplay, CurrentTime);
|
||||
meta_error_trap_pop (window->display);
|
||||
|
||||
window->grab_on_frame = FALSE;
|
||||
@@ -317,29 +418,61 @@ static gboolean
|
||||
is_modifier (MetaDisplay *display,
|
||||
unsigned int keycode)
|
||||
{
|
||||
int i;
|
||||
int map_size;
|
||||
XModifierKeymap *mod_keymap;
|
||||
gboolean retval = FALSE;
|
||||
int i;
|
||||
int map_size;
|
||||
XModifierKeymap *mod_keymap;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
/* FIXME this is ass-slow, cache the modmap */
|
||||
|
||||
mod_keymap = XGetModifierMapping (display->xdisplay);
|
||||
|
||||
map_size = 8 * mod_keymap->max_keypermod;
|
||||
i = 0;
|
||||
while (i < map_size)
|
||||
{
|
||||
if (keycode == mod_keymap->modifiermap[i])
|
||||
{
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
XFreeModifiermap (mod_keymap);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/* FIXME this is ass-slow, cache the modmap */
|
||||
|
||||
mod_keymap = XGetModifierMapping (display->xdisplay);
|
||||
|
||||
map_size = 8 * mod_keymap->max_keypermod;
|
||||
i = 0;
|
||||
while (i < map_size) {
|
||||
|
||||
if (keycode == mod_keymap->modifiermap[i]) {
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
XFreeModifiermap (mod_keymap);
|
||||
|
||||
return retval;
|
||||
#define MOD1_INDEX 3 /* shift, lock, control, mod1 */
|
||||
static gboolean
|
||||
is_mod1_key (MetaDisplay *display,
|
||||
unsigned int keycode)
|
||||
{
|
||||
int i;
|
||||
int end;
|
||||
XModifierKeymap *mod_keymap;
|
||||
gboolean retval = FALSE;
|
||||
|
||||
/* FIXME this is ass-slow, cache the modmap */
|
||||
|
||||
mod_keymap = XGetModifierMapping (display->xdisplay);
|
||||
|
||||
end = (MOD1_INDEX + 1) * mod_keymap->max_keypermod;
|
||||
i = MOD1_INDEX * mod_keymap->max_keypermod;
|
||||
while (i < end)
|
||||
{
|
||||
if (keycode == mod_keymap->modifiermap[i])
|
||||
{
|
||||
retval = TRUE;
|
||||
break;
|
||||
}
|
||||
++i;
|
||||
}
|
||||
|
||||
XFreeModifiermap (mod_keymap);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -391,50 +524,81 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
|
||||
if (window)
|
||||
process_event (window_bindings, display, window, event, keysym);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return;
|
||||
|
||||
/* If we get here we have a global grab, because
|
||||
* we're in some special keyboard mode such as window move
|
||||
* mode.
|
||||
*/
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_NONE)
|
||||
return;
|
||||
|
||||
/* don't end grabs on modifier key presses */
|
||||
if (is_modifier (display, event->xkey.keycode))
|
||||
return;
|
||||
handled = FALSE;
|
||||
|
||||
if (window == display->grab_window)
|
||||
{
|
||||
switch (display->grab_op)
|
||||
{
|
||||
case META_GRAB_OP_KEYBOARD_MOVING:
|
||||
meta_verbose ("Processing event for keyboard move\n");
|
||||
handled = process_keyboard_move_grab (display, window, event, keysym);
|
||||
break;
|
||||
case META_GRAB_OP_KEYBOARD_TABBING:
|
||||
meta_verbose ("Processing event for keyboard tabbing\n");
|
||||
handled = process_tab_grab (display, window, event, keysym);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* end grab if a key that isn't used gets pressed */
|
||||
if (!handled)
|
||||
{
|
||||
meta_verbose ("Ending grab op %d on key event sym %s\n",
|
||||
display->grab_op, XKeysymToString (keysym));
|
||||
meta_display_end_grab_op (display, event->xkey.time);
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_keyboard_move_grab (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
KeySym keysym)
|
||||
{
|
||||
gboolean handled;
|
||||
int x, y;
|
||||
int incr;
|
||||
gboolean smart_snap;
|
||||
int edge;
|
||||
|
||||
handled = FALSE;
|
||||
|
||||
if (display->grab_op == META_GRAB_OP_KEYBOARD_MOVING &&
|
||||
display->grab_window == window)
|
||||
{
|
||||
int x, y;
|
||||
int incr;
|
||||
gboolean smart_snap;
|
||||
int edge;
|
||||
|
||||
if (event->type == KeyRelease)
|
||||
return; /* don't care about releases */
|
||||
|
||||
if (window == NULL)
|
||||
meta_bug ("NULL window while doing keyboard grab op\n");
|
||||
/* don't care about releases, but eat them, don't end grab */
|
||||
if (event->type == KeyRelease)
|
||||
return TRUE;
|
||||
|
||||
meta_window_get_position (window, &x, &y);
|
||||
/* don't end grab on modifier key presses */
|
||||
if (is_modifier (display, event->xkey.keycode))
|
||||
return TRUE;
|
||||
|
||||
smart_snap = (event->xkey.state & ShiftMask) != 0;
|
||||
meta_window_get_position (window, &x, &y);
|
||||
|
||||
smart_snap = (event->xkey.state & ShiftMask) != 0;
|
||||
|
||||
#define SMALL_INCREMENT 1
|
||||
#define NORMAL_INCREMENT 10
|
||||
|
||||
if (smart_snap)
|
||||
incr = 0;
|
||||
else if (event->xkey.state & ControlMask)
|
||||
incr = SMALL_INCREMENT;
|
||||
else
|
||||
incr = NORMAL_INCREMENT;
|
||||
if (smart_snap)
|
||||
incr = 0;
|
||||
else if (event->xkey.state & ControlMask)
|
||||
incr = SMALL_INCREMENT;
|
||||
else
|
||||
incr = NORMAL_INCREMENT;
|
||||
|
||||
/* When moving by increments, we still snap to edges if the move
|
||||
* to the edge is smaller than the increment. This is because
|
||||
@@ -442,71 +606,139 @@ meta_display_process_key_event (MetaDisplay *display,
|
||||
* people using just arrows shouldn't get too frustrated.
|
||||
*/
|
||||
|
||||
switch (keysym)
|
||||
{
|
||||
case XK_Up:
|
||||
case XK_KP_Up:
|
||||
edge = meta_window_find_next_horizontal_edge (window, FALSE);
|
||||
y -= incr;
|
||||
|
||||
if (smart_snap || ((edge > y) && ABS (edge - y) < incr))
|
||||
y = edge;
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
case XK_Down:
|
||||
case XK_KP_Down:
|
||||
edge = meta_window_find_next_horizontal_edge (window, TRUE);
|
||||
y += incr;
|
||||
|
||||
if (smart_snap || ((edge < y) && ABS (edge - y) < incr))
|
||||
y = edge;
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
case XK_Left:
|
||||
case XK_KP_Left:
|
||||
edge = meta_window_find_next_vertical_edge (window, FALSE);
|
||||
x -= incr;
|
||||
|
||||
if (smart_snap || ((edge > x) && ABS (edge - x) < incr))
|
||||
x = edge;
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
case XK_Right:
|
||||
case XK_KP_Right:
|
||||
edge = meta_window_find_next_vertical_edge (window, TRUE);
|
||||
x += incr;
|
||||
if (smart_snap || ((edge < x) && ABS (edge - x) < incr))
|
||||
x = edge;
|
||||
handled = TRUE;
|
||||
break;
|
||||
|
||||
case XK_Escape:
|
||||
/* End move and restore to original position */
|
||||
meta_window_move_resize (display->grab_window,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
display->grab_initial_window_pos.width,
|
||||
display->grab_initial_window_pos.height);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
meta_window_move (window, x, y);
|
||||
}
|
||||
|
||||
/* end grab if a key that isn't used gets pressed */
|
||||
if (!handled)
|
||||
switch (keysym)
|
||||
{
|
||||
meta_verbose ("Ending grab op %d on key press event sym %s\n",
|
||||
display->grab_op, XKeysymToString (keysym));
|
||||
meta_display_end_grab_op (display, event->xkey.time);
|
||||
case XK_Up:
|
||||
case XK_KP_Up:
|
||||
edge = meta_window_find_next_horizontal_edge (window, FALSE);
|
||||
y -= incr;
|
||||
|
||||
if (smart_snap || ((edge > y) && ABS (edge - y) < incr))
|
||||
y = edge;
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
case XK_Down:
|
||||
case XK_KP_Down:
|
||||
edge = meta_window_find_next_horizontal_edge (window, TRUE);
|
||||
y += incr;
|
||||
|
||||
if (smart_snap || ((edge < y) && ABS (edge - y) < incr))
|
||||
y = edge;
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
case XK_Left:
|
||||
case XK_KP_Left:
|
||||
edge = meta_window_find_next_vertical_edge (window, FALSE);
|
||||
x -= incr;
|
||||
|
||||
if (smart_snap || ((edge > x) && ABS (edge - x) < incr))
|
||||
x = edge;
|
||||
|
||||
handled = TRUE;
|
||||
break;
|
||||
case XK_Right:
|
||||
case XK_KP_Right:
|
||||
edge = meta_window_find_next_vertical_edge (window, TRUE);
|
||||
x += incr;
|
||||
if (smart_snap || ((edge < x) && ABS (edge - x) < incr))
|
||||
x = edge;
|
||||
handled = TRUE;
|
||||
break;
|
||||
|
||||
case XK_Escape:
|
||||
/* End move and restore to original position */
|
||||
meta_window_move_resize (display->grab_window,
|
||||
TRUE,
|
||||
display->grab_initial_window_pos.x,
|
||||
display->grab_initial_window_pos.y,
|
||||
display->grab_initial_window_pos.width,
|
||||
display->grab_initial_window_pos.height);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (handled)
|
||||
meta_window_move (window, TRUE, x, y);
|
||||
|
||||
return handled;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
process_tab_grab (MetaDisplay *display,
|
||||
MetaWindow *window,
|
||||
XEvent *event,
|
||||
KeySym keysym)
|
||||
{
|
||||
MetaScreen *screen;
|
||||
|
||||
window = NULL; /* be sure we don't use this, it's irrelevant */
|
||||
|
||||
screen = display->grab_window->screen;
|
||||
|
||||
g_return_val_if_fail (screen->tab_popup != NULL, FALSE);
|
||||
|
||||
if (event->type == KeyRelease &&
|
||||
is_mod1_key (display, event->xkey.keycode))
|
||||
{
|
||||
/* We're done, move to the new window. */
|
||||
Window target_xwindow;
|
||||
MetaWindow *target_window;
|
||||
|
||||
target_xwindow =
|
||||
meta_ui_tab_popup_get_selected (screen->tab_popup);
|
||||
target_window =
|
||||
meta_display_lookup_x_window (display, target_xwindow);
|
||||
|
||||
meta_verbose ("Ending tab operation, Mod1 released\n");
|
||||
|
||||
if (target_window)
|
||||
{
|
||||
meta_verbose ("Ending grab early so we can focus the target window\n");
|
||||
meta_display_end_grab_op (display, event->xkey.time);
|
||||
|
||||
meta_verbose ("Focusing target window\n");
|
||||
meta_window_raise (target_window);
|
||||
meta_window_focus (target_window, event->xkey.time);
|
||||
|
||||
return TRUE; /* we already ended the grab */
|
||||
}
|
||||
|
||||
return FALSE; /* end grab */
|
||||
}
|
||||
|
||||
/* don't care about other releases, but eat them, don't end grab */
|
||||
if (event->type == KeyRelease)
|
||||
return TRUE;
|
||||
|
||||
/* don't end grab on modifier key presses */
|
||||
if (is_modifier (display, event->xkey.keycode))
|
||||
return TRUE;
|
||||
|
||||
switch (keysym)
|
||||
{
|
||||
case XK_ISO_Left_Tab:
|
||||
case XK_Tab:
|
||||
if (event->xkey.state & ShiftMask)
|
||||
meta_ui_tab_popup_backward (screen->tab_popup);
|
||||
else
|
||||
meta_ui_tab_popup_forward (screen->tab_popup);
|
||||
|
||||
/* continue grab */
|
||||
meta_verbose ("Tab key pressed, moving tab focus in popup\n");
|
||||
return TRUE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* end grab */
|
||||
meta_verbose ("Ending tabbing, uninteresting key pressed\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -670,6 +902,7 @@ handle_tab_forward (MetaDisplay *display,
|
||||
if (display->focus_window != NULL)
|
||||
{
|
||||
window = meta_stack_get_tab_next (display->focus_window->screen->stack,
|
||||
display->focus_window->screen->active_workspace,
|
||||
display->focus_window,
|
||||
FALSE);
|
||||
}
|
||||
@@ -687,15 +920,30 @@ handle_tab_forward (MetaDisplay *display,
|
||||
if (screen)
|
||||
{
|
||||
window = meta_stack_get_tab_next (screen->stack,
|
||||
event_window,
|
||||
screen->active_workspace,
|
||||
NULL,
|
||||
FALSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, event->xkey.time);
|
||||
meta_verbose ("Starting tab forward, showing popup\n");
|
||||
|
||||
meta_display_begin_grab_op (window->display,
|
||||
display->focus_window ?
|
||||
display->focus_window : window,
|
||||
META_GRAB_OP_KEYBOARD_TABBING,
|
||||
FALSE,
|
||||
0, 0,
|
||||
event->xkey.time,
|
||||
0, 0);
|
||||
|
||||
meta_ui_tab_popup_select (window->screen->tab_popup,
|
||||
window->xwindow);
|
||||
/* only after selecting proper window */
|
||||
meta_ui_tab_popup_set_showing (window->screen->tab_popup,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -714,6 +962,7 @@ handle_tab_backward (MetaDisplay *display,
|
||||
if (display->focus_window != NULL)
|
||||
{
|
||||
window = meta_stack_get_tab_next (display->focus_window->screen->stack,
|
||||
display->focus_window->screen->active_workspace,
|
||||
display->focus_window,
|
||||
TRUE);
|
||||
}
|
||||
@@ -731,15 +980,30 @@ handle_tab_backward (MetaDisplay *display,
|
||||
if (screen)
|
||||
{
|
||||
window = meta_stack_get_tab_next (screen->stack,
|
||||
event_window,
|
||||
screen->active_workspace,
|
||||
NULL,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
if (window)
|
||||
{
|
||||
meta_window_raise (window);
|
||||
meta_window_focus (window, event->xkey.time);
|
||||
meta_verbose ("Starting tab backward, showing popup\n");
|
||||
|
||||
meta_display_begin_grab_op (window->display,
|
||||
display->focus_window ?
|
||||
display->focus_window : window,
|
||||
META_GRAB_OP_KEYBOARD_TABBING,
|
||||
FALSE,
|
||||
0, 0,
|
||||
event->xkey.time,
|
||||
0, 0);
|
||||
|
||||
meta_ui_tab_popup_select (window->screen->tab_popup,
|
||||
window->xwindow);
|
||||
/* only after selecting proper window */
|
||||
meta_ui_tab_popup_set_showing (window->screen->tab_popup,
|
||||
TRUE);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -750,29 +1014,36 @@ handle_focus_previous (MetaDisplay *display,
|
||||
gpointer data)
|
||||
{
|
||||
MetaWindow *window;
|
||||
|
||||
MetaScreen *screen;
|
||||
|
||||
meta_verbose ("Focus previous window\n");
|
||||
|
||||
screen = meta_display_screen_for_root (display,
|
||||
event->xkey.root);
|
||||
|
||||
if (screen == NULL)
|
||||
return;
|
||||
|
||||
window = display->prev_focus_window;
|
||||
|
||||
if (window &&
|
||||
!meta_workspace_contains_window (screen->active_workspace,
|
||||
window))
|
||||
window = NULL;
|
||||
|
||||
if (window == NULL)
|
||||
{
|
||||
/* Pick first window in tab order */
|
||||
MetaScreen *screen;
|
||||
|
||||
screen = meta_display_screen_for_root (display,
|
||||
event->xkey.root);
|
||||
|
||||
/* We get the screen because event_window may be NULL,
|
||||
* in which case we can't use event_window->screen
|
||||
*/
|
||||
if (screen)
|
||||
{
|
||||
window = meta_stack_get_tab_next (screen->stack,
|
||||
event_window,
|
||||
TRUE);
|
||||
}
|
||||
/* Pick first window in tab order */
|
||||
window = meta_stack_get_tab_next (screen->stack,
|
||||
screen->active_workspace,
|
||||
NULL,
|
||||
TRUE);
|
||||
}
|
||||
|
||||
if (window &&
|
||||
!meta_workspace_contains_window (screen->active_workspace,
|
||||
window))
|
||||
window = NULL;
|
||||
|
||||
if (window)
|
||||
{
|
||||
|
24
src/main.c
24
src/main.c
@@ -38,11 +38,20 @@
|
||||
static MetaExitCode meta_exit_code = META_EXIT_SUCCESS;
|
||||
static GMainLoop *meta_main_loop = NULL;
|
||||
|
||||
static void
|
||||
log_handler (const gchar *log_domain,
|
||||
GLogLevelFlags log_level,
|
||||
const gchar *message,
|
||||
gpointer user_data)
|
||||
{
|
||||
meta_warning ("GLib log level %d: %s\n", log_level, message);
|
||||
}
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
g_print ("metacity [--disable-sm] [--sm-client-id=ID] [--display=DISPLAY]\n");
|
||||
exit (0);
|
||||
exit (1);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -153,10 +162,7 @@ main (int argc, char **argv)
|
||||
{
|
||||
putenv (display_name);
|
||||
/* DO NOT FREE display_name, putenv() sucks */
|
||||
}
|
||||
|
||||
/* gtk_init() below overrides this, so it can be removed */
|
||||
meta_errors_init ();
|
||||
}
|
||||
|
||||
g_type_init ();
|
||||
|
||||
@@ -164,6 +170,14 @@ main (int argc, char **argv)
|
||||
meta_session_init (client_id); /* client_id == NULL is fine */
|
||||
|
||||
meta_ui_init (&argc, &argv);
|
||||
|
||||
/* must be after UI init so we can override GDK handlers */
|
||||
meta_errors_init ();
|
||||
|
||||
g_log_set_handler (NULL,
|
||||
G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
|
||||
log_handler, NULL);
|
||||
g_log_set_always_fatal (G_LOG_LEVEL_MASK);
|
||||
|
||||
if (!meta_display_open (NULL))
|
||||
meta_exit (META_EXIT_ERROR);
|
||||
|
10
src/menu.c
10
src/menu.c
@@ -168,6 +168,12 @@ meta_window_menu_new (MetaFrames *frames,
|
||||
META_FRAME_CONTROL_MAXIMIZE,
|
||||
&pix, &mask);
|
||||
break;
|
||||
|
||||
case META_MENU_OP_UNMAXIMIZE:
|
||||
meta_frames_get_pixmap_for_control (frames,
|
||||
META_FRAME_CONTROL_UNMAXIMIZE,
|
||||
&pix, &mask);
|
||||
break;
|
||||
|
||||
case META_MENU_OP_MINIMIZE:
|
||||
meta_frames_get_pixmap_for_control (frames,
|
||||
@@ -251,10 +257,10 @@ meta_window_menu_new (MetaFrames *frames,
|
||||
MenuData *md;
|
||||
|
||||
if (ops & META_MENU_OP_UNSTICK)
|
||||
label = g_strdup_printf (_("Only on workspace _%d\n"),
|
||||
label = g_strdup_printf (_("Only on workspace _%d"),
|
||||
i + 1);
|
||||
else
|
||||
label = g_strdup_printf (_("Move to workspace _%d\n"),
|
||||
label = g_strdup_printf (_("Move to workspace _%d"),
|
||||
i + 1);
|
||||
|
||||
mi = gtk_menu_item_new_with_mnemonic (label);
|
||||
|
6
src/metacity.desktop
Normal file
6
src/metacity.desktop
Normal file
@@ -0,0 +1,6 @@
|
||||
[Desktop Entry]
|
||||
Name=Metacity
|
||||
Exec=metacity
|
||||
|
||||
[Window Manager]
|
||||
SessionManaged=true
|
12
src/place.c
12
src/place.c
@@ -220,7 +220,11 @@ meta_window_place (MetaWindow *window,
|
||||
*/
|
||||
|
||||
meta_verbose ("Placing window %s\n", window->desc);
|
||||
|
||||
|
||||
/* FIXME copying Mac, when placing a dialog
|
||||
* put it at 1/5 down and horizontally centered
|
||||
*/
|
||||
|
||||
if (window->xtransient_for != None)
|
||||
{
|
||||
/* Center horizontally, at top of parent vertically */
|
||||
@@ -249,6 +253,12 @@ meta_window_place (MetaWindow *window,
|
||||
meta_verbose ("Centered window %s over transient parent\n",
|
||||
window->desc);
|
||||
|
||||
if (parent->has_focus)
|
||||
{
|
||||
meta_verbose ("Focusing transient window since parent had focus\n");
|
||||
meta_window_focus (window, CurrentTime); /* FIXME CurrentTime */
|
||||
}
|
||||
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
@@ -22,9 +22,14 @@ if test -n "$EVIL_TEST"; then
|
||||
TEST_CLIENT='./wm-tester/wm-tester --evil'
|
||||
fi
|
||||
|
||||
if test -n "$ICON_TEST"; then
|
||||
TEST_CLIENT='./wm-tester/wm-tester --icon-windows'
|
||||
fi
|
||||
|
||||
if test -z "$ONLY_WM"; then
|
||||
Xnest -ac :1 -scrns $SCREENS -geometry 640x480 -bw 15 &
|
||||
usleep 500000
|
||||
## usleep 800000
|
||||
sleep 1
|
||||
|
||||
if test -n "$TEST_CLIENT"; then
|
||||
DISPLAY=:1 $TEST_CLIENT &
|
||||
@@ -32,12 +37,14 @@ if test -z "$ONLY_WM"; then
|
||||
|
||||
if test $CLIENTS != 0; then
|
||||
for I in `seq 1 $CLIENTS`; do
|
||||
echo "Launching xterm $I"
|
||||
DISPLAY=:1 xterm -geometry 25x15 &
|
||||
done
|
||||
fi
|
||||
|
||||
if test $SM_CLIENTS != 0; then
|
||||
for I in `seq 1 $SM_CLIENTS`; do
|
||||
echo "Launching gnome-terminal $I"
|
||||
DISPLAY=:1 gnome-terminal --geometry 25x15 &
|
||||
done
|
||||
fi
|
||||
|
113
src/screen.c
113
src/screen.c
@@ -72,7 +72,7 @@ set_wm_check_hint (MetaScreen *screen)
|
||||
static int
|
||||
set_supported_hint (MetaScreen *screen)
|
||||
{
|
||||
#define N_SUPPORTED 21
|
||||
#define N_SUPPORTED 23
|
||||
#define N_WIN_SUPPORTED 1
|
||||
Atom atoms[N_SUPPORTED];
|
||||
|
||||
@@ -97,9 +97,11 @@ set_supported_hint (MetaScreen *screen)
|
||||
atoms[18] = screen->display->atom_net_client_list_stacking;
|
||||
atoms[19] = screen->display->atom_net_wm_state_skip_taskbar;
|
||||
atoms[20] = screen->display->atom_net_wm_state_skip_pager;
|
||||
atoms[21] = screen->display->atom_net_wm_icon;
|
||||
atoms[22] = screen->display->atom_net_wm_moveresize;
|
||||
|
||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||
screen->display->atom_net_wm_supported,
|
||||
screen->display->atom_net_supported,
|
||||
XA_ATOM,
|
||||
32, PropModeReplace, (guchar*) atoms, N_SUPPORTED);
|
||||
|
||||
@@ -115,6 +117,29 @@ set_supported_hint (MetaScreen *screen)
|
||||
#undef N_SUPPORTED
|
||||
}
|
||||
|
||||
static int
|
||||
set_wm_icon_size_hint (MetaScreen *screen)
|
||||
{
|
||||
#define N_VALS 6
|
||||
gulong vals[N_VALS];
|
||||
|
||||
/* min width, min height, max w, max h, width inc, height inc */
|
||||
vals[0] = META_ICON_WIDTH;
|
||||
vals[1] = META_ICON_HEIGHT;
|
||||
vals[2] = META_ICON_WIDTH;
|
||||
vals[3] = META_ICON_HEIGHT;
|
||||
vals[4] = 0;
|
||||
vals[5] = 0;
|
||||
|
||||
XChangeProperty (screen->display->xdisplay, screen->xroot,
|
||||
screen->display->atom_wm_icon_size,
|
||||
XA_CARDINAL,
|
||||
32, PropModeReplace, (guchar*) vals, N_VALS);
|
||||
|
||||
return Success;
|
||||
#undef N_VALS
|
||||
}
|
||||
|
||||
MetaScreen*
|
||||
meta_screen_new (MetaDisplay *display,
|
||||
int number)
|
||||
@@ -170,6 +195,8 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->width = WidthOfScreen (screen->xscreen);
|
||||
screen->height = HeightOfScreen (screen->xscreen);
|
||||
screen->current_cursor = -1; /* invalid/unset */
|
||||
screen->default_xvisual = DefaultVisualOfScreen (screen->xscreen);
|
||||
screen->default_depth = DefaultDepthOfScreen (screen->xscreen);
|
||||
|
||||
meta_screen_set_cursor (screen, META_CURSOR_DEFAULT);
|
||||
|
||||
@@ -177,6 +204,8 @@ meta_screen_new (MetaDisplay *display,
|
||||
display->leader_window = XCreateSimpleWindow (display->xdisplay,
|
||||
screen->xroot,
|
||||
-100, -100, 1, 1, 0, 0, 0);
|
||||
|
||||
set_wm_icon_size_hint (screen);
|
||||
|
||||
set_supported_hint (screen);
|
||||
|
||||
@@ -198,6 +227,8 @@ meta_screen_new (MetaDisplay *display,
|
||||
screen->ui = meta_ui_new (screen->display->xdisplay,
|
||||
screen->xscreen);
|
||||
|
||||
screen->tab_popup = NULL;
|
||||
|
||||
screen->stack = meta_stack_new (screen);
|
||||
|
||||
meta_verbose ("Added screen %d ('%s') root 0x%lx\n",
|
||||
@@ -210,7 +241,7 @@ void
|
||||
meta_screen_free (MetaScreen *screen)
|
||||
{
|
||||
meta_screen_ungrab_keys (screen);
|
||||
|
||||
|
||||
meta_ui_free (screen->ui);
|
||||
|
||||
meta_stack_free (screen->stack);
|
||||
@@ -423,3 +454,79 @@ meta_screen_set_cursor (MetaScreen *screen,
|
||||
XDefineCursor (screen->display->xdisplay, screen->xroot, xcursor);
|
||||
XFreeCursor (screen->display->xdisplay, xcursor);
|
||||
}
|
||||
|
||||
void
|
||||
meta_screen_ensure_tab_popup (MetaScreen *screen)
|
||||
{
|
||||
MetaTabEntry *entries;
|
||||
GSList *tab_list;
|
||||
GSList *tmp;
|
||||
int len;
|
||||
int i;
|
||||
|
||||
if (screen->tab_popup)
|
||||
return;
|
||||
|
||||
tab_list = meta_stack_get_tab_list (screen->stack,
|
||||
screen->active_workspace);
|
||||
len = g_slist_length (tab_list);
|
||||
|
||||
entries = g_new (MetaTabEntry, len + 1);
|
||||
entries[len].xwindow = None;
|
||||
entries[len].title = NULL;
|
||||
entries[len].icon = NULL;
|
||||
|
||||
i = 0;
|
||||
tmp = tab_list;
|
||||
while (i < len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
MetaRectangle r;
|
||||
|
||||
window = tmp->data;
|
||||
|
||||
entries[i].xwindow = window->xwindow;
|
||||
entries[i].title = window->title;
|
||||
entries[i].icon = window->icon;
|
||||
meta_window_get_outer_rect (window, &r);
|
||||
entries[i].x = r.x;
|
||||
entries[i].y = r.y;
|
||||
entries[i].width = r.width;
|
||||
entries[i].height = r.height;
|
||||
|
||||
/* Find inside of highlight rectangle to be used
|
||||
* when window is outlined for tabbing.
|
||||
* This should be the size of the east/west frame,
|
||||
* and the size of the south frame, on those sides.
|
||||
* on the top it should be the size of the south frame
|
||||
* edge.
|
||||
*/
|
||||
if (window->frame)
|
||||
{
|
||||
int south = window->frame->rect.height - window->frame->child_y -
|
||||
window->rect.height;
|
||||
int east = window->frame->child_x;
|
||||
entries[i].inner_x = east;
|
||||
entries[i].inner_y = south;
|
||||
entries[i].inner_width = window->rect.width;
|
||||
entries[i].inner_height = window->frame->rect.height - south * 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Use an arbitrary border size */
|
||||
#define OUTLINE_WIDTH 5
|
||||
entries[i].inner_x = OUTLINE_WIDTH;
|
||||
entries[i].inner_y = OUTLINE_WIDTH;
|
||||
entries[i].inner_width = window->rect.width - OUTLINE_WIDTH * 2;
|
||||
entries[i].inner_height = window->rect.height - OUTLINE_WIDTH * 2;
|
||||
}
|
||||
|
||||
++i;
|
||||
tmp = tmp->next;
|
||||
}
|
||||
|
||||
screen->tab_popup = meta_ui_tab_popup_new (entries);
|
||||
g_free (entries);
|
||||
|
||||
/* don't show tab popup, since proper window isn't selected yet */
|
||||
}
|
||||
|
@@ -36,10 +36,13 @@ struct _MetaScreen
|
||||
char *screen_name;
|
||||
Screen *xscreen;
|
||||
Window xroot;
|
||||
int default_depth;
|
||||
Visual *default_xvisual;
|
||||
int width;
|
||||
int height;
|
||||
MetaUI *ui;
|
||||
|
||||
MetaTabPopup *tab_popup;
|
||||
|
||||
MetaWorkspace *active_workspace;
|
||||
|
||||
MetaStack *stack;
|
||||
@@ -63,6 +66,8 @@ int meta_screen_get_n_workspaces (MetaScreen *scree
|
||||
void meta_screen_set_cursor (MetaScreen *screen,
|
||||
MetaCursor cursor);
|
||||
|
||||
void meta_screen_ensure_tab_popup (MetaScreen *screen);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
@@ -77,8 +77,10 @@ process_ice_messages (GIOChannel *channel,
|
||||
/* We were disconnected */
|
||||
IceSetShutdownNegotiation (connection, False);
|
||||
IceCloseConnection (connection);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
@@ -97,8 +99,8 @@ new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
|
||||
*/
|
||||
GIOChannel *channel;
|
||||
|
||||
fcntl (IceConnectionNumber(connection),F_SETFD,
|
||||
fcntl(IceConnectionNumber(connection),F_GETFD,0) | FD_CLOEXEC);
|
||||
fcntl (IceConnectionNumber (connection), F_SETFD,
|
||||
fcntl (IceConnectionNumber (connection), F_GETFD, 0) | FD_CLOEXEC);
|
||||
|
||||
channel = g_io_channel_unix_new (IceConnectionNumber (connection));
|
||||
|
||||
@@ -119,15 +121,15 @@ new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
|
||||
}
|
||||
}
|
||||
|
||||
static IceIOErrorHandler gnome_ice_installed_handler;
|
||||
static IceIOErrorHandler ice_installed_handler;
|
||||
|
||||
/* We call any handler installed before (or after) gnome_ice_init but
|
||||
avoid calling the default libICE handler which does an exit() */
|
||||
static void
|
||||
ice_io_error_handler (IceConn connection)
|
||||
{
|
||||
if (gnome_ice_installed_handler)
|
||||
(*gnome_ice_installed_handler) (connection);
|
||||
if (ice_installed_handler)
|
||||
(*ice_installed_handler) (connection);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -139,11 +141,11 @@ ice_init (void)
|
||||
{
|
||||
IceIOErrorHandler default_handler;
|
||||
|
||||
gnome_ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||
ice_installed_handler = IceSetIOErrorHandler (NULL);
|
||||
default_handler = IceSetIOErrorHandler (ice_io_error_handler);
|
||||
|
||||
if (gnome_ice_installed_handler == default_handler)
|
||||
gnome_ice_installed_handler = NULL;
|
||||
if (ice_installed_handler == default_handler)
|
||||
ice_installed_handler = NULL;
|
||||
|
||||
IceAddConnectionWatch (new_ice_connection, NULL);
|
||||
|
||||
@@ -244,10 +246,11 @@ meta_session_init (const char *previous_id)
|
||||
current_state = STATE_REGISTERING;
|
||||
|
||||
{
|
||||
SmProp prop1, prop2, prop3, prop4, prop5, *props[5];
|
||||
SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val;
|
||||
SmProp prop1, prop2, prop3, prop4, prop5, prop6, *props[6];
|
||||
SmPropValue prop1val, prop2val, prop3val, prop4val, prop5val, prop6val;
|
||||
char pid[32];
|
||||
char hint = SmRestartIfRunning;
|
||||
char priority = 20; /* low to run before other apps */
|
||||
|
||||
prop1.name = SmProgram;
|
||||
prop1.type = SmARRAY8;
|
||||
@@ -288,14 +291,22 @@ meta_session_init (const char *previous_id)
|
||||
prop5.vals = &prop5val;
|
||||
prop5val.value = g_get_home_dir ();
|
||||
prop5val.length = strlen (prop5val.value);
|
||||
|
||||
prop6.name = "_GSM_Priority";
|
||||
prop6.type = SmCARD8;
|
||||
prop6.num_vals = 1;
|
||||
prop6.vals = &prop6val;
|
||||
prop6val.value = &priority;
|
||||
prop6val.length = 1;
|
||||
|
||||
props[0] = &prop1;
|
||||
props[1] = &prop2;
|
||||
props[2] = &prop3;
|
||||
props[3] = &prop4;
|
||||
props[4] = &prop5;
|
||||
props[5] = &prop6;
|
||||
|
||||
SmcSetProperties (session_connection, 5, props);
|
||||
SmcSetProperties (session_connection, 6, props);
|
||||
}
|
||||
|
||||
set_clone_restart_commands ();
|
||||
@@ -563,6 +574,9 @@ window_type_to_string (MetaWindowType type)
|
||||
case META_WINDOW_MENU:
|
||||
return "menu";
|
||||
break;
|
||||
case META_WINDOW_FULLSCREEN:
|
||||
return "fullscreen";
|
||||
break;
|
||||
}
|
||||
|
||||
return "";
|
||||
@@ -585,6 +599,8 @@ window_type_from_string (const char *str)
|
||||
return META_WINDOW_TOOLBAR;
|
||||
else if (strcmp (str, "menu") == 0)
|
||||
return META_WINDOW_MENU;
|
||||
else if (strcmp (str, "fullscreen") == 0)
|
||||
return META_WINDOW_FULLSCREEN;
|
||||
else
|
||||
return META_WINDOW_NORMAL;
|
||||
}
|
||||
@@ -658,13 +674,14 @@ window_gravity_from_string (const char *str)
|
||||
}
|
||||
|
||||
static char*
|
||||
encode_text_as_utf8 (const char *text)
|
||||
encode_text_as_utf8_markup (const char *text)
|
||||
{
|
||||
/* text can be any encoding, and is nul-terminated.
|
||||
* we pretend it's Latin-1 and encode as UTF-8
|
||||
*/
|
||||
GString *str;
|
||||
const char *p;
|
||||
char *escaped;
|
||||
|
||||
str = g_string_new ("");
|
||||
|
||||
@@ -675,13 +692,16 @@ encode_text_as_utf8 (const char *text)
|
||||
++p;
|
||||
}
|
||||
|
||||
return g_string_free (str, FALSE);
|
||||
escaped = g_markup_escape_text (str->str, str->len);
|
||||
g_string_free (str, TRUE);
|
||||
|
||||
return escaped;
|
||||
}
|
||||
|
||||
static char*
|
||||
decode_text_from_utf8 (const char *text)
|
||||
{
|
||||
/* Convert back from the encoded UTF-8 */
|
||||
/* Convert back from the encoded (but not escaped) UTF-8 */
|
||||
GString *str;
|
||||
const char *p;
|
||||
|
||||
@@ -796,13 +816,13 @@ save_state (void)
|
||||
* in practice they are always ascii though.)
|
||||
*/
|
||||
|
||||
sm_client_id = encode_text_as_utf8 (window->sm_client_id);
|
||||
sm_client_id = encode_text_as_utf8_markup (window->sm_client_id);
|
||||
res_class = window->res_class ?
|
||||
encode_text_as_utf8 (window->res_class) : NULL;
|
||||
encode_text_as_utf8_markup (window->res_class) : NULL;
|
||||
res_name = window->res_name ?
|
||||
encode_text_as_utf8 (window->res_name) : NULL;
|
||||
encode_text_as_utf8_markup (window->res_name) : NULL;
|
||||
role = window->role ?
|
||||
encode_text_as_utf8 (window->role) : NULL;
|
||||
encode_text_as_utf8_markup (window->role) : NULL;
|
||||
|
||||
meta_verbose ("Saving session managed window %s, client ID '%s'\n",
|
||||
window->desc, window->sm_client_id);
|
||||
@@ -874,11 +894,17 @@ save_state (void)
|
||||
out:
|
||||
if (outfile)
|
||||
{
|
||||
if (fclose (outfile) != 0)
|
||||
/* FIXME need a dialog for this */
|
||||
if (ferror (outfile))
|
||||
{
|
||||
meta_warning (_("Error writing session file '%s': %s\n"),
|
||||
session_file, g_strerror (errno));
|
||||
}
|
||||
if (fclose (outfile))
|
||||
{
|
||||
meta_warning (_("Error closing session file '%s': %s\n"),
|
||||
session_file, g_strerror (errno));
|
||||
}
|
||||
}
|
||||
|
||||
g_free (metacity_dir);
|
||||
|
173
src/stack.c
173
src/stack.c
@@ -62,6 +62,8 @@ meta_stack_new (MetaScreen *screen)
|
||||
stack->pending = NULL;
|
||||
stack->freeze_count = 0;
|
||||
stack->n_added = 0;
|
||||
|
||||
stack->last_root_children_stacked = NULL;
|
||||
|
||||
return stack;
|
||||
}
|
||||
@@ -95,6 +97,10 @@ meta_stack_free (MetaStack *stack)
|
||||
}
|
||||
|
||||
g_list_free (stack->pending);
|
||||
|
||||
g_array_free (stack->last_root_children_stacked, TRUE);
|
||||
|
||||
g_free (stack);
|
||||
}
|
||||
|
||||
static MetaStackOp*
|
||||
@@ -259,9 +265,14 @@ compute_layer (MetaWindow *window)
|
||||
break;
|
||||
|
||||
case META_WINDOW_DOCK:
|
||||
window->layer = META_LAYER_DOCK;
|
||||
/* still experimenting here */
|
||||
window->layer = META_LAYER_NORMAL;
|
||||
break;
|
||||
|
||||
case META_WINDOW_FULLSCREEN:
|
||||
window->layer = META_LAYER_FULLSCREEN;
|
||||
break;
|
||||
|
||||
default:
|
||||
window->layer = META_LAYER_NORMAL;
|
||||
break;
|
||||
@@ -630,9 +641,101 @@ meta_stack_sync_to_server (MetaStack *stack)
|
||||
root_children_stacked->len);
|
||||
|
||||
meta_error_trap_push (stack->screen->display);
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *) root_children_stacked->data,
|
||||
root_children_stacked->len);
|
||||
|
||||
if (stack->last_root_children_stacked == NULL)
|
||||
{
|
||||
/* Just impose our stack, we don't know the previous state.
|
||||
* This involves a ton of circulate requests and may flicker.
|
||||
*/
|
||||
meta_verbose ("Don't know last stack state, restacking everything\n");
|
||||
|
||||
if (root_children_stacked->len > 0)
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *) root_children_stacked->data,
|
||||
root_children_stacked->len);
|
||||
}
|
||||
else if (root_children_stacked->len > 0)
|
||||
{
|
||||
/* Try to do minimal window moves to get the stack in order */
|
||||
/* A point of note: these arrays include frames not client windows,
|
||||
* so if a client window has changed frame since last_root_children_stacked
|
||||
* as saved, then we may have inefficiency, but I don't think things
|
||||
* break...
|
||||
*/
|
||||
const Window *old_stack = (Window *) stack->last_root_children_stacked->data;
|
||||
const Window *new_stack = (Window *) root_children_stacked->data;
|
||||
const int old_len = stack->last_root_children_stacked->len;
|
||||
const int new_len = root_children_stacked->len;
|
||||
const Window *oldp = old_stack;
|
||||
const Window *newp = new_stack;
|
||||
const Window *old_end = old_stack + old_len;
|
||||
const Window *new_end = new_stack + new_len;
|
||||
Window last_window = None;
|
||||
|
||||
while (oldp != old_end &&
|
||||
newp != new_end)
|
||||
{
|
||||
if (*oldp == *newp)
|
||||
{
|
||||
/* Stacks are the same here, move on */
|
||||
++oldp;
|
||||
++newp;
|
||||
}
|
||||
else if (meta_display_lookup_x_window (stack->screen->display,
|
||||
*oldp) == NULL)
|
||||
{
|
||||
/* *oldp is no longer known to us (probably destroyed),
|
||||
* so we can just skip it
|
||||
*/
|
||||
++oldp;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Move *newp below last_window */
|
||||
if (last_window == None)
|
||||
{
|
||||
meta_verbose ("Raising window 0x%lx to the top\n", *newp);
|
||||
|
||||
XRaiseWindow (stack->screen->display->xdisplay,
|
||||
*newp);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* This means that if last_window is dead, but not
|
||||
* *newp, then we fail to restack *newp; but on
|
||||
* unmanaging last_window, we'll fix it up.
|
||||
*/
|
||||
|
||||
XWindowChanges changes;
|
||||
|
||||
changes.sibling = last_window;
|
||||
changes.stack_mode = Below;
|
||||
|
||||
meta_verbose ("Placing window 0x%lx below 0x%lx\n",
|
||||
*newp, last_window);
|
||||
|
||||
XConfigureWindow (stack->screen->display->xdisplay,
|
||||
*newp,
|
||||
CWSibling | CWStackMode,
|
||||
&changes);
|
||||
}
|
||||
|
||||
++newp;
|
||||
}
|
||||
|
||||
last_window = *newp;
|
||||
}
|
||||
|
||||
if (newp != new_end)
|
||||
{
|
||||
/* Restack remaining windows */
|
||||
meta_verbose ("Restacking remaining %d windows\n",
|
||||
(int) (new_end - newp));
|
||||
XRestackWindows (stack->screen->display->xdisplay,
|
||||
(Window *) newp, new_end - newp);
|
||||
}
|
||||
}
|
||||
|
||||
meta_error_trap_pop (stack->screen->display);
|
||||
/* on error, a window was destroyed; it should eventually
|
||||
* get removed from the stacking list when we unmanage it
|
||||
@@ -657,8 +760,11 @@ meta_stack_sync_to_server (MetaStack *stack)
|
||||
stacked->len);
|
||||
|
||||
g_array_free (stacked, TRUE);
|
||||
g_array_free (root_children_stacked, TRUE);
|
||||
|
||||
if (stack->last_root_children_stacked)
|
||||
g_array_free (stack->last_root_children_stacked, TRUE);
|
||||
stack->last_root_children_stacked = root_children_stacked;
|
||||
|
||||
/* That was scary... */
|
||||
}
|
||||
|
||||
@@ -858,12 +964,23 @@ find_tab_backward (MetaStack *stack,
|
||||
|
||||
/* This ignores the dock/desktop layers */
|
||||
MetaWindow*
|
||||
meta_stack_get_tab_next (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
gboolean backward)
|
||||
meta_stack_get_tab_next (MetaStack *stack,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *window,
|
||||
gboolean backward)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (workspace && window)
|
||||
{
|
||||
/* This is a paranoia check, because races can happen where
|
||||
* you get a key shortcut or something on a window just as you
|
||||
* are moving workspaces to one the window isn't on
|
||||
*/
|
||||
if (!meta_workspace_contains_window (workspace, window))
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (stack->windows->len == 0)
|
||||
return NULL;
|
||||
|
||||
@@ -877,11 +994,7 @@ meta_stack_get_tab_next (MetaStack *stack,
|
||||
w = g_array_index (stack->windows, Window, i);
|
||||
|
||||
if (w == window->xwindow)
|
||||
{
|
||||
MetaWorkspace *workspace;
|
||||
|
||||
workspace = window->screen->active_workspace;
|
||||
|
||||
{
|
||||
if (backward)
|
||||
return find_tab_backward (stack, workspace, i);
|
||||
else
|
||||
@@ -896,10 +1009,40 @@ meta_stack_get_tab_next (MetaStack *stack,
|
||||
* window and we need to wrap around
|
||||
*/
|
||||
if (backward)
|
||||
return find_tab_backward (stack, NULL,
|
||||
return find_tab_backward (stack, workspace,
|
||||
stack->windows->len);
|
||||
else
|
||||
return find_tab_forward (stack, NULL, -1);
|
||||
return find_tab_forward (stack, workspace, -1);
|
||||
}
|
||||
|
||||
GSList*
|
||||
meta_stack_get_tab_list (MetaStack *stack,
|
||||
MetaWorkspace *workspace)
|
||||
{
|
||||
GSList *list;
|
||||
int i;
|
||||
|
||||
list = NULL;
|
||||
|
||||
i = 0;
|
||||
while (i < stack->windows->len)
|
||||
{
|
||||
MetaWindow *window;
|
||||
|
||||
window = meta_display_lookup_x_window (stack->screen->display,
|
||||
GET_XWINDOW (stack, i));
|
||||
|
||||
if (window && IN_TAB_CHAIN (window) &&
|
||||
(workspace == NULL ||
|
||||
meta_workspace_contains_window (workspace, window)))
|
||||
list = g_slist_prepend (list, window);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
list = g_slist_reverse (list);
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
int
|
||||
|
26
src/stack.h
26
src/stack.h
@@ -32,12 +32,13 @@ typedef struct _MetaStackOp MetaStackOp;
|
||||
/* These MUST be in the order of stacking */
|
||||
typedef enum
|
||||
{
|
||||
META_LAYER_DESKTOP = 0,
|
||||
META_LAYER_BOTTOM = 1,
|
||||
META_LAYER_NORMAL = 2,
|
||||
META_LAYER_TOP = 3,
|
||||
META_LAYER_DOCK = 4,
|
||||
META_LAYER_LAST = 5
|
||||
META_LAYER_DESKTOP = 0,
|
||||
META_LAYER_BOTTOM = 1,
|
||||
META_LAYER_NORMAL = 2,
|
||||
META_LAYER_TOP = 3,
|
||||
META_LAYER_DOCK = 4,
|
||||
META_LAYER_FULLSCREEN = 5,
|
||||
META_LAYER_LAST = 6
|
||||
} MetaStackLayer;
|
||||
|
||||
struct _MetaStack
|
||||
@@ -60,6 +61,9 @@ struct _MetaStack
|
||||
int freeze_count;
|
||||
|
||||
int n_added;
|
||||
|
||||
/* The last-known stack */
|
||||
GArray *last_root_children_stacked;
|
||||
};
|
||||
|
||||
MetaStack *meta_stack_new (MetaScreen *screen);
|
||||
@@ -92,9 +96,13 @@ MetaWindow* meta_stack_get_above (MetaStack *stack,
|
||||
MetaWindow* meta_stack_get_below (MetaStack *stack,
|
||||
MetaWindow *window);
|
||||
|
||||
MetaWindow* meta_stack_get_tab_next (MetaStack *stack,
|
||||
MetaWindow *window,
|
||||
gboolean backward);
|
||||
MetaWindow* meta_stack_get_tab_next (MetaStack *stack,
|
||||
MetaWorkspace *workspace,
|
||||
MetaWindow *window,
|
||||
gboolean backward);
|
||||
GSList* meta_stack_get_tab_list (MetaStack *stack,
|
||||
MetaWorkspace *workspace);
|
||||
|
||||
/* -1 if a < b, etc. */
|
||||
int meta_stack_windows_cmp (MetaStack *stack,
|
||||
MetaWindow *window_a,
|
||||
|
551
src/tabpopup.c
Normal file
551
src/tabpopup.c
Normal file
@@ -0,0 +1,551 @@
|
||||
/* Metacity popup window thing showing windows you can tab to */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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 "util.h"
|
||||
#include "core.h"
|
||||
#include "tabpopup.h"
|
||||
#include <math.h>
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
#define OUTSIDE_SELECT_RECT 2
|
||||
#define INSIDE_SELECT_RECT 2
|
||||
|
||||
typedef struct _TabEntry TabEntry;
|
||||
|
||||
struct _TabEntry
|
||||
{
|
||||
Window xwindow;
|
||||
char *title;
|
||||
GdkPixbuf *icon;
|
||||
GtkWidget *widget;
|
||||
GdkRectangle rect;
|
||||
GdkRectangle inner_rect;
|
||||
};
|
||||
|
||||
struct _MetaTabPopup
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *label;
|
||||
GList *current;
|
||||
GList *entries;
|
||||
TabEntry *current_selected_entry;
|
||||
GtkWidget *outline_window;
|
||||
};
|
||||
|
||||
static GtkWidget* selectable_image_new (GdkPixbuf *pixbuf);
|
||||
static void select_image (GtkWidget *widget);
|
||||
static void unselect_image (GtkWidget *widget);
|
||||
|
||||
static gboolean
|
||||
outline_window_expose (GtkWidget *widget,
|
||||
GdkEventExpose *event,
|
||||
gpointer data)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
int w, h;
|
||||
TabEntry *te;
|
||||
|
||||
popup = data;
|
||||
|
||||
if (popup->current_selected_entry == NULL)
|
||||
return FALSE;
|
||||
|
||||
te = popup->current_selected_entry;
|
||||
|
||||
gdk_window_get_size (widget->window, &w, &h);
|
||||
|
||||
gdk_draw_rectangle (widget->window,
|
||||
widget->style->white_gc,
|
||||
FALSE,
|
||||
0, 0,
|
||||
te->rect.width - 1,
|
||||
te->rect.height - 1);
|
||||
|
||||
gdk_draw_rectangle (widget->window,
|
||||
widget->style->white_gc,
|
||||
FALSE,
|
||||
te->inner_rect.x - 1, te->inner_rect.y - 1,
|
||||
te->inner_rect.width + 1,
|
||||
te->inner_rect.height + 1);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
MetaTabPopup*
|
||||
meta_ui_tab_popup_new (const MetaTabEntry *entries)
|
||||
{
|
||||
MetaTabPopup *popup;
|
||||
int i, left, right, top, bottom;
|
||||
GList *tab_entries;
|
||||
int width;
|
||||
int height;
|
||||
GtkWidget *table;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *align;
|
||||
GList *tmp;
|
||||
GtkWidget *frame;
|
||||
int max_label_width;
|
||||
|
||||
popup = g_new (MetaTabPopup, 1);
|
||||
|
||||
popup->outline_window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
gtk_widget_set_app_paintable (popup->outline_window, TRUE);
|
||||
gtk_widget_realize (popup->outline_window);
|
||||
|
||||
g_signal_connect (G_OBJECT (popup->outline_window), "expose_event",
|
||||
G_CALLBACK (outline_window_expose), popup);
|
||||
|
||||
popup->window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
gtk_window_set_position (GTK_WINDOW (popup->window),
|
||||
GTK_WIN_POS_CENTER_ALWAYS);
|
||||
/* enable resizing, to get never-shrink behavior */
|
||||
gtk_window_set_resizable (GTK_WINDOW (popup->window),
|
||||
TRUE);
|
||||
popup->current = NULL;
|
||||
popup->entries = NULL;
|
||||
popup->current_selected_entry = NULL;
|
||||
|
||||
tab_entries = NULL;
|
||||
i = 0;
|
||||
while (entries[i].xwindow != None)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = g_new (TabEntry, 1);
|
||||
te->xwindow = entries[i].xwindow;
|
||||
te->title = g_strdup (entries[i].title);
|
||||
te->icon = entries[i].icon;
|
||||
g_object_ref (G_OBJECT (te->icon));
|
||||
te->widget = NULL;
|
||||
|
||||
te->rect.x = entries[i].x;
|
||||
te->rect.y = entries[i].y;
|
||||
te->rect.width = entries[i].width;
|
||||
te->rect.height = entries[i].height;
|
||||
|
||||
te->inner_rect.x = entries[i].inner_x;
|
||||
te->inner_rect.y = entries[i].inner_y;
|
||||
te->inner_rect.width = entries[i].inner_width;
|
||||
te->inner_rect.height = entries[i].inner_height;
|
||||
|
||||
tab_entries = g_list_prepend (tab_entries, te);
|
||||
|
||||
++i;
|
||||
}
|
||||
|
||||
popup->entries = g_list_reverse (tab_entries);
|
||||
|
||||
width = 5; /* FIXME */
|
||||
height = i / width;
|
||||
if (i % width)
|
||||
height += 1;
|
||||
|
||||
table = gtk_table_new (height, width, FALSE);
|
||||
vbox = gtk_vbox_new (FALSE, 0);
|
||||
|
||||
frame = gtk_frame_new (NULL);
|
||||
gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
|
||||
gtk_container_set_border_width (GTK_CONTAINER (table), 1);
|
||||
gtk_container_add (GTK_CONTAINER (popup->window),
|
||||
frame);
|
||||
gtk_container_add (GTK_CONTAINER (frame),
|
||||
vbox);
|
||||
|
||||
align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
|
||||
|
||||
gtk_box_pack_start (GTK_BOX (vbox), align, TRUE, TRUE, 0);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (align),
|
||||
table);
|
||||
|
||||
popup->label = gtk_label_new ("");
|
||||
gtk_misc_set_padding (GTK_MISC (popup->label), 3, 3);
|
||||
|
||||
gtk_box_pack_end (GTK_BOX (vbox), popup->label, FALSE, FALSE, 0);
|
||||
|
||||
max_label_width = 0;
|
||||
top = 0;
|
||||
bottom = 1;
|
||||
tmp = popup->entries;
|
||||
|
||||
while (tmp && top < height)
|
||||
{
|
||||
left = 0;
|
||||
right = 1;
|
||||
|
||||
while (tmp && left < width)
|
||||
{
|
||||
GtkWidget *image;
|
||||
GtkRequisition req;
|
||||
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
image = selectable_image_new (te->icon);
|
||||
gtk_misc_set_padding (GTK_MISC (image),
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1,
|
||||
INSIDE_SELECT_RECT + OUTSIDE_SELECT_RECT + 1);
|
||||
gtk_misc_set_alignment (GTK_MISC (image), 0.5, 0.5);
|
||||
|
||||
te->widget = image;
|
||||
|
||||
gtk_table_attach (GTK_TABLE (table),
|
||||
te->widget,
|
||||
left, right, top, bottom,
|
||||
0, 0,
|
||||
0, 0);
|
||||
|
||||
/* Efficiency rules! */
|
||||
gtk_label_set_text (GTK_LABEL (popup->label),
|
||||
te->title);
|
||||
gtk_widget_size_request (popup->label, &req);
|
||||
max_label_width = MAX (max_label_width, req.width);
|
||||
|
||||
tmp = tmp->next;
|
||||
|
||||
++left;
|
||||
++right;
|
||||
}
|
||||
|
||||
++top;
|
||||
++bottom;
|
||||
}
|
||||
|
||||
/* remove all the temporary text */
|
||||
gtk_label_set_text (GTK_LABEL (popup->label), "");
|
||||
|
||||
max_label_width += 20; /* add random padding */
|
||||
|
||||
gtk_window_set_default_size (GTK_WINDOW (popup->window),
|
||||
max_label_width,
|
||||
-1);
|
||||
|
||||
return popup;
|
||||
}
|
||||
|
||||
static void
|
||||
free_entry (gpointer data, gpointer user_data)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = data;
|
||||
|
||||
g_free (te->title);
|
||||
g_object_unref (G_OBJECT (te->icon));
|
||||
|
||||
g_free (te);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_free (MetaTabPopup *popup)
|
||||
{
|
||||
gtk_widget_destroy (popup->outline_window);
|
||||
gtk_widget_destroy (popup->window);
|
||||
|
||||
g_list_foreach (popup->entries, free_entry, NULL);
|
||||
|
||||
g_list_free (popup->entries);
|
||||
|
||||
g_free (popup);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing)
|
||||
{
|
||||
if (showing)
|
||||
gtk_widget_show_all (popup->window);
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (popup->window);
|
||||
meta_core_increment_event_serial (gdk_display);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
display_entry (MetaTabPopup *popup,
|
||||
TabEntry *te)
|
||||
{
|
||||
GdkRectangle rect;
|
||||
GdkRegion *region;
|
||||
GdkRegion *inner_region;
|
||||
|
||||
|
||||
if (popup->current_selected_entry)
|
||||
unselect_image (popup->current_selected_entry->widget);
|
||||
|
||||
gtk_label_set_text (GTK_LABEL (popup->label), te->title);
|
||||
select_image (te->widget);
|
||||
|
||||
/* Do stuff behind gtk's back */
|
||||
gdk_window_hide (popup->outline_window->window);
|
||||
meta_core_increment_event_serial (gdk_display);
|
||||
|
||||
rect = te->rect;
|
||||
rect.x = 0;
|
||||
rect.y = 0;
|
||||
|
||||
gdk_window_move_resize (popup->outline_window->window,
|
||||
te->rect.x, te->rect.y,
|
||||
te->rect.width, te->rect.height);
|
||||
|
||||
gdk_window_set_background (popup->outline_window->window,
|
||||
&popup->outline_window->style->black);
|
||||
|
||||
region = gdk_region_rectangle (&rect);
|
||||
inner_region = gdk_region_rectangle (&te->inner_rect);
|
||||
gdk_region_subtract (region, inner_region);
|
||||
gdk_region_destroy (inner_region);
|
||||
|
||||
gdk_window_shape_combine_region (popup->outline_window->window,
|
||||
region,
|
||||
0, 0);
|
||||
|
||||
gdk_region_destroy (region);
|
||||
|
||||
/* This should piss off gtk a bit, but we don't want to raise
|
||||
* above the tab popup
|
||||
*/
|
||||
gdk_window_show_unraised (popup->outline_window->window);
|
||||
|
||||
/* Must be before we handle an expose for the outline window */
|
||||
popup->current_selected_entry = te;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_forward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->next;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = popup->entries;
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_backward (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current != NULL)
|
||||
popup->current = popup->current->prev;
|
||||
|
||||
if (popup->current == NULL)
|
||||
popup->current = g_list_last (popup->entries);
|
||||
|
||||
if (popup->current != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
display_entry (popup, te);
|
||||
}
|
||||
}
|
||||
|
||||
Window
|
||||
meta_ui_tab_popup_get_selected (MetaTabPopup *popup)
|
||||
{
|
||||
if (popup->current)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = popup->current->data;
|
||||
|
||||
return te->xwindow;
|
||||
}
|
||||
else
|
||||
return None;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
Window xwindow)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
tmp = popup->entries;
|
||||
while (tmp != NULL)
|
||||
{
|
||||
TabEntry *te;
|
||||
|
||||
te = tmp->data;
|
||||
|
||||
if (te->xwindow == xwindow)
|
||||
{
|
||||
popup->current = tmp;
|
||||
|
||||
display_entry (popup, te);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
tmp = tmp->next;
|
||||
}
|
||||
}
|
||||
|
||||
#define META_TYPE_SELECT_IMAGE (meta_select_image_get_type ())
|
||||
#define META_SELECT_IMAGE(obj) (GTK_CHECK_CAST ((obj), META_TYPE_SELECT_IMAGE, MetaSelectImage))
|
||||
|
||||
typedef struct _MetaSelectImage MetaSelectImage;
|
||||
typedef struct _MetaSelectImageClass MetaSelectImageClass;
|
||||
|
||||
struct _MetaSelectImage
|
||||
{
|
||||
GtkImage parent_instance;
|
||||
guint selected : 1;
|
||||
};
|
||||
|
||||
struct _MetaSelectImageClass
|
||||
{
|
||||
GtkImageClass parent_class;
|
||||
};
|
||||
|
||||
|
||||
static GType meta_select_image_get_type (void) G_GNUC_CONST;
|
||||
|
||||
static GtkWidget*
|
||||
selectable_image_new (GdkPixbuf *pixbuf)
|
||||
{
|
||||
GtkWidget *w;
|
||||
|
||||
w = g_object_new (meta_select_image_get_type (), NULL);
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (w), pixbuf);
|
||||
|
||||
return w;
|
||||
}
|
||||
|
||||
static void
|
||||
select_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = TRUE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void
|
||||
unselect_image (GtkWidget *widget)
|
||||
{
|
||||
META_SELECT_IMAGE (widget)->selected = FALSE;
|
||||
gtk_widget_queue_draw (widget);
|
||||
}
|
||||
|
||||
static void meta_select_image_class_init (MetaSelectImageClass *klass);
|
||||
static gboolean meta_select_image_expose_event (GtkWidget *widget,
|
||||
GdkEventExpose *event);
|
||||
|
||||
static GtkImageClass *parent_class;
|
||||
|
||||
GType
|
||||
meta_select_image_get_type (void)
|
||||
{
|
||||
static GtkType image_type = 0;
|
||||
|
||||
if (!image_type)
|
||||
{
|
||||
static const GTypeInfo image_info =
|
||||
{
|
||||
sizeof (MetaSelectImageClass),
|
||||
NULL, /* base_init */
|
||||
NULL, /* base_finalize */
|
||||
(GClassInitFunc) meta_select_image_class_init,
|
||||
NULL, /* class_finalize */
|
||||
NULL, /* class_data */
|
||||
sizeof (MetaSelectImage),
|
||||
16, /* n_preallocs */
|
||||
(GInstanceInitFunc) NULL,
|
||||
};
|
||||
|
||||
image_type = g_type_register_static (GTK_TYPE_IMAGE, "MetaSelectImage", &image_info, 0);
|
||||
}
|
||||
|
||||
return image_type;
|
||||
}
|
||||
|
||||
static void
|
||||
meta_select_image_class_init (MetaSelectImageClass *klass)
|
||||
{
|
||||
GtkWidgetClass *widget_class;
|
||||
|
||||
parent_class = gtk_type_class (gtk_image_get_type ());
|
||||
|
||||
widget_class = GTK_WIDGET_CLASS (klass);
|
||||
|
||||
widget_class->expose_event = meta_select_image_expose_event;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
meta_select_image_expose_event (GtkWidget *widget,
|
||||
GdkEventExpose *event)
|
||||
{
|
||||
if (META_SELECT_IMAGE (widget)->selected)
|
||||
{
|
||||
int x, y, w, h;
|
||||
GtkMisc *misc;
|
||||
|
||||
misc = GTK_MISC (widget);
|
||||
|
||||
x = (widget->allocation.x * (1.0 - misc->xalign) +
|
||||
(widget->allocation.x + widget->allocation.width
|
||||
- (widget->requisition.width - misc->xpad * 2)) *
|
||||
misc->xalign) + 0.5;
|
||||
y = (widget->allocation.y * (1.0 - misc->yalign) +
|
||||
(widget->allocation.y + widget->allocation.height
|
||||
- (widget->requisition.height - misc->ypad * 2)) *
|
||||
misc->yalign) + 0.5;
|
||||
|
||||
x -= INSIDE_SELECT_RECT + 1;
|
||||
y -= INSIDE_SELECT_RECT + 1;
|
||||
|
||||
w = widget->requisition.width - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
h = widget->requisition.height - OUTSIDE_SELECT_RECT * 2 - 1;
|
||||
|
||||
gdk_draw_rectangle (widget->window,
|
||||
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
|
||||
FALSE,
|
||||
x, y, w, h);
|
||||
gdk_draw_rectangle (widget->window,
|
||||
widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
|
||||
FALSE,
|
||||
x - 1, y - 1, w + 2, h + 2);
|
||||
|
||||
#if 0
|
||||
gdk_draw_rectangle (widget->window,
|
||||
widget->style->bg_gc[GTK_STATE_SELECTED],
|
||||
TRUE,
|
||||
x, y, w, h);
|
||||
#endif
|
||||
#if 0
|
||||
gtk_paint_focus (widget->style, widget->window,
|
||||
&event->area, widget, "meta-tab-image",
|
||||
x, y, w, h);
|
||||
#endif
|
||||
}
|
||||
|
||||
return GTK_WIDGET_CLASS (parent_class)->expose_event (widget, event);
|
||||
}
|
55
src/tabpopup.h
Normal file
55
src/tabpopup.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/* Metacity tab popup window */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2001 Havoc Pennington
|
||||
*
|
||||
* 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_TABPOPUP_H
|
||||
#define META_TABPOPUP_H
|
||||
|
||||
/* Don't include gtk.h or gdk.h here */
|
||||
#include "common.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <glib.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct _MetaTabEntry MetaTabEntry;
|
||||
typedef struct _MetaTabPopup MetaTabPopup;
|
||||
|
||||
struct _MetaTabEntry
|
||||
{
|
||||
Window xwindow;
|
||||
const char *title;
|
||||
GdkPixbuf *icon;
|
||||
int x, y, width, height;
|
||||
int inner_x, inner_y, inner_width, inner_height;
|
||||
};
|
||||
|
||||
MetaTabPopup* meta_ui_tab_popup_new (const MetaTabEntry *entries);
|
||||
void meta_ui_tab_popup_free (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_set_showing (MetaTabPopup *popup,
|
||||
gboolean showing);
|
||||
void meta_ui_tab_popup_forward (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_backward (MetaTabPopup *popup);
|
||||
Window meta_ui_tab_popup_get_selected (MetaTabPopup *popup);
|
||||
void meta_ui_tab_popup_select (MetaTabPopup *popup,
|
||||
Window xwindow);
|
||||
|
||||
|
||||
#endif
|
||||
|
306
src/ui.c
306
src/ui.c
@@ -19,10 +19,14 @@
|
||||
* 02111-1307, USA.
|
||||
*/
|
||||
|
||||
#include <config.h>
|
||||
#include "ui.h"
|
||||
#include "frames.h"
|
||||
#include "util.h"
|
||||
#include "menu.h"
|
||||
#include "core.h"
|
||||
|
||||
#include "inlinepixbufs.h"
|
||||
|
||||
struct _MetaUI
|
||||
{
|
||||
@@ -35,7 +39,16 @@ void
|
||||
meta_ui_init (int *argc, char ***argv)
|
||||
{
|
||||
if (!gtk_init_check (argc, argv))
|
||||
meta_fatal ("Unable to open X display %s\n", gdk_display_name);
|
||||
meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL));
|
||||
|
||||
{
|
||||
/* FIXME this is a hackaround for a GTK bug with using menus without
|
||||
* menubars. we have to use the get_type value since it's G_GNUC_CONST
|
||||
*/
|
||||
volatile GType t;
|
||||
t = gtk_menu_bar_get_type ();
|
||||
t += 5;
|
||||
}
|
||||
}
|
||||
|
||||
Display*
|
||||
@@ -171,7 +184,7 @@ meta_ui_unmap_frame (MetaUI *ui,
|
||||
|
||||
window = gdk_xid_table_lookup (xwindow);
|
||||
|
||||
if (window)
|
||||
if (window)
|
||||
gdk_window_hide (window);
|
||||
}
|
||||
|
||||
@@ -232,3 +245,292 @@ meta_ui_window_menu_free (MetaWindowMenu *menu)
|
||||
meta_window_menu_free (menu);
|
||||
}
|
||||
|
||||
struct _MetaImageWindow
|
||||
{
|
||||
GtkWidget *window;
|
||||
GtkWidget *image;
|
||||
};
|
||||
|
||||
MetaImageWindow*
|
||||
meta_image_window_new (void)
|
||||
{
|
||||
MetaImageWindow *iw;
|
||||
|
||||
iw = g_new (MetaImageWindow, 1);
|
||||
iw->window = gtk_window_new (GTK_WINDOW_POPUP);
|
||||
iw->image = g_object_new (GTK_TYPE_IMAGE, NULL);
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (iw->window), iw->image);
|
||||
|
||||
/* Ensure we auto-shrink to fit image */
|
||||
gtk_window_set_resizable (GTK_WINDOW (iw->window),
|
||||
FALSE);
|
||||
|
||||
return iw;
|
||||
}
|
||||
|
||||
void
|
||||
meta_image_window_free (MetaImageWindow *iw)
|
||||
{
|
||||
gtk_widget_destroy (iw->window);
|
||||
g_free (iw);
|
||||
}
|
||||
|
||||
void
|
||||
meta_image_window_set_showing (MetaImageWindow *iw,
|
||||
gboolean showing)
|
||||
{
|
||||
if (showing)
|
||||
gtk_widget_show_all (iw->window);
|
||||
else
|
||||
{
|
||||
gtk_widget_hide (iw->window);
|
||||
meta_core_increment_event_serial (gdk_display);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
meta_image_window_set_image (MetaImageWindow *iw,
|
||||
GdkPixbuf *pixbuf)
|
||||
{
|
||||
gtk_image_set_from_pixbuf (GTK_IMAGE (iw->image), pixbuf);
|
||||
}
|
||||
|
||||
void
|
||||
meta_image_window_set_position (MetaImageWindow *iw,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
/* We want to do move/resize at the same time to avoid ugliness.
|
||||
* Lame hack.
|
||||
*/
|
||||
GtkRequisition req;
|
||||
|
||||
g_return_if_fail (GTK_WIDGET_REALIZED (iw->window));
|
||||
|
||||
gtk_widget_size_request (iw->window, &req);
|
||||
|
||||
gdk_window_move_resize (GTK_WIDGET (iw->window)->window,
|
||||
x, y, req.width, req.height);
|
||||
}
|
||||
|
||||
static GdkColormap*
|
||||
get_cmap (GdkPixmap *pixmap)
|
||||
{
|
||||
GdkColormap *cmap;
|
||||
|
||||
cmap = gdk_drawable_get_colormap (pixmap);
|
||||
if (cmap)
|
||||
g_object_ref (G_OBJECT (cmap));
|
||||
|
||||
if (cmap == NULL)
|
||||
{
|
||||
if (gdk_drawable_get_depth (pixmap) == 1)
|
||||
{
|
||||
meta_verbose ("Using NULL colormap for snapshotting bitmap\n");
|
||||
cmap = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
meta_verbose ("Using system cmap to snapshot pixmap\n");
|
||||
cmap = gdk_colormap_get_system ();
|
||||
g_object_ref (G_OBJECT (cmap));
|
||||
}
|
||||
}
|
||||
|
||||
return cmap;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
|
||||
Window xwindow,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkDrawable *drawable;
|
||||
GdkPixbuf *retval;
|
||||
GdkColormap *cmap;
|
||||
|
||||
retval = NULL;
|
||||
|
||||
drawable = gdk_xid_table_lookup (xwindow);
|
||||
|
||||
if (drawable)
|
||||
g_object_ref (G_OBJECT (drawable));
|
||||
else
|
||||
drawable = gdk_window_foreign_new (xwindow);
|
||||
|
||||
cmap = get_cmap (drawable);
|
||||
|
||||
retval = gdk_pixbuf_get_from_drawable (dest,
|
||||
drawable,
|
||||
cmap,
|
||||
src_x, src_y,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
|
||||
if (cmap)
|
||||
g_object_unref (G_OBJECT (cmap));
|
||||
g_object_unref (G_OBJECT (drawable));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest,
|
||||
Pixmap xpixmap,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height)
|
||||
{
|
||||
GdkDrawable *drawable;
|
||||
GdkPixbuf *retval;
|
||||
GdkColormap *cmap;
|
||||
|
||||
retval = NULL;
|
||||
|
||||
drawable = gdk_xid_table_lookup (xpixmap);
|
||||
|
||||
if (drawable)
|
||||
g_object_ref (G_OBJECT (drawable));
|
||||
else
|
||||
drawable = gdk_pixmap_foreign_new (xpixmap);
|
||||
|
||||
cmap = get_cmap (drawable);
|
||||
|
||||
retval = gdk_pixbuf_get_from_drawable (dest,
|
||||
drawable,
|
||||
cmap,
|
||||
src_x, src_y,
|
||||
dest_x, dest_y,
|
||||
width, height);
|
||||
|
||||
if (cmap)
|
||||
g_object_unref (G_OBJECT (cmap));
|
||||
g_object_unref (G_OBJECT (drawable));
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_push_delay_exposes (MetaUI *ui)
|
||||
{
|
||||
meta_frames_push_delay_exposes (ui->frames);
|
||||
}
|
||||
|
||||
void
|
||||
meta_ui_pop_delay_exposes (MetaUI *ui)
|
||||
{
|
||||
meta_frames_pop_delay_exposes (ui->frames);
|
||||
}
|
||||
|
||||
#ifdef HAVE_GDK_PIXBUF_NEW_FROM_STREAM
|
||||
#define gdk_pixbuf_new_from_inline gdk_pixbuf_new_from_stream
|
||||
#endif
|
||||
|
||||
GdkPixbuf*
|
||||
meta_ui_get_default_window_icon (MetaUI *ui)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GdkPixbuf *base;
|
||||
|
||||
base = gdk_pixbuf_new_from_inline (-1, default_icon_data,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
g_assert (base);
|
||||
|
||||
default_icon = gdk_pixbuf_scale_simple (base,
|
||||
META_ICON_WIDTH,
|
||||
META_ICON_HEIGHT,
|
||||
GDK_INTERP_BILINEAR);
|
||||
|
||||
g_object_unref (G_OBJECT (base));
|
||||
}
|
||||
|
||||
g_object_ref (G_OBJECT (default_icon));
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
GdkPixbuf*
|
||||
meta_ui_get_default_mini_icon (MetaUI *ui)
|
||||
{
|
||||
static GdkPixbuf *default_icon = NULL;
|
||||
|
||||
if (default_icon == NULL)
|
||||
{
|
||||
GdkPixbuf *base;
|
||||
|
||||
base = gdk_pixbuf_new_from_inline (-1, default_icon_data,
|
||||
FALSE,
|
||||
NULL);
|
||||
|
||||
g_assert (base);
|
||||
|
||||
default_icon = gdk_pixbuf_scale_simple (base,
|
||||
META_MINI_ICON_WIDTH,
|
||||
META_MINI_ICON_HEIGHT,
|
||||
GDK_INTERP_BILINEAR);
|
||||
|
||||
g_object_unref (G_OBJECT (base));
|
||||
}
|
||||
|
||||
g_object_ref (G_OBJECT (default_icon));
|
||||
|
||||
return default_icon;
|
||||
}
|
||||
|
||||
gboolean
|
||||
meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow)
|
||||
{
|
||||
GdkWindow *window;
|
||||
|
||||
window = gdk_xid_table_lookup (xwindow);
|
||||
|
||||
/* we shouldn't cause focus if we're an override redirect
|
||||
* toplevel which is not foreign
|
||||
*/
|
||||
if (window && gdk_window_get_type (window) == GDK_WINDOW_TEMP)
|
||||
return TRUE;
|
||||
else
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
char*
|
||||
meta_text_property_to_utf8 (Display *xdisplay,
|
||||
const XTextProperty *prop)
|
||||
{
|
||||
char **list;
|
||||
int count;
|
||||
char *retval;
|
||||
|
||||
list = NULL;
|
||||
|
||||
count = gdk_text_property_to_utf8_list (prop->encoding,
|
||||
prop->format,
|
||||
prop->value,
|
||||
prop->nitems,
|
||||
&list);
|
||||
|
||||
if (count == 0)
|
||||
return NULL;
|
||||
|
||||
retval = list[0];
|
||||
list[0] = g_strdup (""); /* something to free */
|
||||
|
||||
g_strfreev (list);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
53
src/ui.h
53
src/ui.h
@@ -22,13 +22,17 @@
|
||||
#ifndef META_UI_H
|
||||
#define META_UI_H
|
||||
|
||||
/* Don't include gtk.h here */
|
||||
/* Don't include gtk.h or gdk.h here */
|
||||
#include "common.h"
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <glib.h>
|
||||
#include <gdk-pixbuf/gdk-pixbuf.h>
|
||||
|
||||
typedef struct _MetaUI MetaUI;
|
||||
|
||||
typedef struct _MetaImageWindow MetaImageWindow;
|
||||
|
||||
typedef gboolean (* MetaEventFunc) (XEvent *xevent, gpointer data);
|
||||
|
||||
void meta_ui_init (int *argc, char ***argv);
|
||||
@@ -88,5 +92,52 @@ void meta_ui_window_menu_popup (MetaWindowMenu *menu,
|
||||
void meta_ui_window_menu_free (MetaWindowMenu *menu);
|
||||
|
||||
|
||||
MetaImageWindow* meta_image_window_new (void);
|
||||
void meta_image_window_free (MetaImageWindow *iw);
|
||||
void meta_image_window_set_showing (MetaImageWindow *iw,
|
||||
gboolean showing);
|
||||
void meta_image_window_set_image (MetaImageWindow *iw,
|
||||
GdkPixbuf *pixbuf);
|
||||
void meta_image_window_set_position (MetaImageWindow *iw,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
/* FIXME these lack a display arg */
|
||||
GdkPixbuf* meta_gdk_pixbuf_get_from_window (GdkPixbuf *dest,
|
||||
Window xwindow,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
GdkPixbuf* meta_gdk_pixbuf_get_from_pixmap (GdkPixbuf *dest,
|
||||
Pixmap xpixmap,
|
||||
int src_x,
|
||||
int src_y,
|
||||
int dest_x,
|
||||
int dest_y,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/* Used when we have a server grab and draw all over everything,
|
||||
* then we need to handle exposes after doing that, instead of
|
||||
* during it
|
||||
*/
|
||||
void meta_ui_push_delay_exposes (MetaUI *ui);
|
||||
void meta_ui_pop_delay_exposes (MetaUI *ui);
|
||||
|
||||
GdkPixbuf* meta_ui_get_default_window_icon (MetaUI *ui);
|
||||
GdkPixbuf* meta_ui_get_default_mini_icon (MetaUI *ui);
|
||||
|
||||
gboolean meta_ui_window_should_not_cause_focus (Display *xdisplay,
|
||||
Window xwindow);
|
||||
|
||||
char* meta_text_property_to_utf8 (Display *xdisplay,
|
||||
const XTextProperty *prop);
|
||||
|
||||
#include "tabpopup.h"
|
||||
|
||||
#endif
|
||||
|
||||
|
@@ -25,6 +25,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static gboolean is_verbose = FALSE;
|
||||
static gboolean is_debugging = FALSE;
|
||||
@@ -42,6 +43,9 @@ ensure_logfile (void)
|
||||
|
||||
dir = g_get_home_dir ();
|
||||
str = g_strconcat (dir, "/", "metacity.log", NULL);
|
||||
|
||||
/* we want to replace not truncate any old logfile */
|
||||
unlink (str);
|
||||
|
||||
logfile = fopen (str, "w");
|
||||
|
||||
|
1486
src/window.c
1486
src/window.c
File diff suppressed because it is too large
Load Diff
48
src/window.h
48
src/window.h
@@ -36,7 +36,8 @@ typedef enum
|
||||
META_WINDOW_DIALOG,
|
||||
META_WINDOW_MODAL_DIALOG,
|
||||
META_WINDOW_TOOLBAR,
|
||||
META_WINDOW_MENU
|
||||
META_WINDOW_MENU,
|
||||
META_WINDOW_FULLSCREEN
|
||||
} MetaWindowType;
|
||||
|
||||
struct _MetaWindow
|
||||
@@ -54,6 +55,7 @@ struct _MetaWindow
|
||||
|
||||
char *icon_name;
|
||||
GdkPixbuf *icon;
|
||||
GdkPixbuf *mini_icon;
|
||||
|
||||
MetaWindowType type;
|
||||
Atom type_atom;
|
||||
@@ -70,11 +72,20 @@ struct _MetaWindow
|
||||
Window xgroup_leader;
|
||||
Window xclient_leader;
|
||||
|
||||
/* Initial workspace property */
|
||||
int initial_workspace;
|
||||
|
||||
Pixmap icon_pixmap;
|
||||
Pixmap icon_mask;
|
||||
|
||||
/* these are legacy and should die once we have _NET_WM_ICON in
|
||||
* most apps
|
||||
*/
|
||||
Pixmap kwm_pixmap;
|
||||
Pixmap kwm_mask;
|
||||
|
||||
/* Initial workspace property */
|
||||
int initial_workspace;
|
||||
/* Whether ->icon is from NET_WM_ICON instead of pixmap */
|
||||
guint using_rgb_icon : 1;
|
||||
|
||||
/* Whether we're maximized */
|
||||
guint maximized : 1;
|
||||
@@ -113,7 +124,7 @@ struct _MetaWindow
|
||||
guint delete_window : 1;
|
||||
/* Globally active / No input */
|
||||
guint input : 1;
|
||||
|
||||
|
||||
/* MWM hints about features of window */
|
||||
guint mwm_decorated : 1;
|
||||
guint mwm_has_close_func : 1;
|
||||
@@ -146,11 +157,9 @@ struct _MetaWindow
|
||||
guint has_focus : 1;
|
||||
|
||||
/* Track whether the user has ever manually modified
|
||||
* the window; if so, we remove some constraints
|
||||
* that exist on program modifications.
|
||||
* the window; if so, we can use the saved user size/pos
|
||||
*/
|
||||
guint user_has_resized : 1;
|
||||
guint user_has_moved : 1;
|
||||
guint user_has_move_resized : 1;
|
||||
|
||||
/* Have we placed this window? */
|
||||
guint placed : 1;
|
||||
@@ -181,7 +190,7 @@ struct _MetaWindow
|
||||
* is withdrawing the window.
|
||||
*/
|
||||
int unmaps_pending;
|
||||
|
||||
|
||||
/* The size we set the window to last (i.e. what we believe
|
||||
* to be its actual size on the server). The x, y are
|
||||
* the actual server-side x,y so are relative to the frame
|
||||
@@ -195,6 +204,17 @@ struct _MetaWindow
|
||||
* above.
|
||||
*/
|
||||
MetaRectangle saved_rect;
|
||||
|
||||
/* This is the geometry the window had after the last user-initiated
|
||||
* move/resize operations. We use this whenever we are moving the
|
||||
* implicitly (for example, if we move to avoid a panel, we
|
||||
* can snap back to this position if the panel moves again)
|
||||
*
|
||||
* Position valid if user_has_moved, size valid if user_has_resized
|
||||
*
|
||||
* Position always in root coords, unlike window->rect
|
||||
*/
|
||||
MetaRectangle user_rect;
|
||||
|
||||
/* Requested geometry */
|
||||
int border_width;
|
||||
@@ -225,17 +245,21 @@ void meta_window_unstick (MetaWindow *window);
|
||||
|
||||
/* args to move are window pos, not frame pos */
|
||||
void meta_window_move (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int root_x_nw,
|
||||
int root_y_nw);
|
||||
void meta_window_resize (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int w,
|
||||
int h);
|
||||
void meta_window_move_resize (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int root_x_nw,
|
||||
int root_y_nw,
|
||||
int w,
|
||||
int h);
|
||||
void meta_window_resize_with_gravity (MetaWindow *window,
|
||||
void meta_window_resize_with_gravity (MetaWindow *window,
|
||||
gboolean user_op,
|
||||
int w,
|
||||
int h,
|
||||
int gravity);
|
||||
@@ -249,6 +273,9 @@ void meta_window_queue_move_resize (MetaWindow *window);
|
||||
void meta_window_get_position (MetaWindow *window,
|
||||
int *x,
|
||||
int *y);
|
||||
void meta_window_get_user_position (MetaWindow *window,
|
||||
int *x,
|
||||
int *y);
|
||||
/* gets position we need to set to stay in current position,
|
||||
* assuming position will be gravity-compensated. i.e.
|
||||
* this is the position a client would send in a configure
|
||||
@@ -272,6 +299,7 @@ void meta_window_delete (MetaWindow *window,
|
||||
void meta_window_focus (MetaWindow *window,
|
||||
Time timestamp);
|
||||
void meta_window_raise (MetaWindow *window);
|
||||
void meta_window_lower (MetaWindow *window);
|
||||
|
||||
|
||||
/* Sends a client message */
|
||||
|
@@ -4,6 +4,10 @@ INCLUDES=@METACITY_CFLAGS@
|
||||
wm_tester_SOURCES= \
|
||||
main.c
|
||||
|
||||
bin_PROGRAMS=wm-tester
|
||||
test_gravity_SOURCES= \
|
||||
test-gravity.c
|
||||
|
||||
noinst_PROGRAMS=wm-tester test-gravity
|
||||
|
||||
wm_tester_LDADD= @METACITY_LIBS@
|
||||
test_gravity_LDADD= @METACITY_LIBS@
|
@@ -28,11 +28,12 @@
|
||||
#include <unistd.h>
|
||||
|
||||
static void set_up_the_evil (void);
|
||||
static void set_up_icon_windows (void);
|
||||
|
||||
static void
|
||||
usage (void)
|
||||
{
|
||||
g_print ("wm-tester [--evil]\n");
|
||||
g_print ("wm-tester [--evil] [--icon-windows]\n");
|
||||
exit (0);
|
||||
}
|
||||
|
||||
@@ -41,10 +42,12 @@ main (int argc, char **argv)
|
||||
{
|
||||
int i;
|
||||
gboolean do_evil;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
gboolean do_icon_windows;
|
||||
|
||||
gtk_init (&argc, &argv);
|
||||
|
||||
do_evil = FALSE;
|
||||
do_icon_windows = FALSE;
|
||||
|
||||
i = 1;
|
||||
while (i < argc)
|
||||
@@ -57,6 +60,8 @@ main (int argc, char **argv)
|
||||
usage ();
|
||||
else if (strcmp (arg, "--evil") == 0)
|
||||
do_evil = TRUE;
|
||||
else if (strcmp (arg, "--icon-windows") == 0)
|
||||
do_icon_windows = TRUE;
|
||||
else
|
||||
usage ();
|
||||
|
||||
@@ -64,12 +69,15 @@ main (int argc, char **argv)
|
||||
}
|
||||
|
||||
/* Be sure some option was provided */
|
||||
if (! (do_evil))
|
||||
if (! (do_evil || do_icon_windows))
|
||||
return 1;
|
||||
|
||||
if (do_evil)
|
||||
set_up_the_evil ();
|
||||
|
||||
|
||||
if (do_icon_windows)
|
||||
set_up_icon_windows ();
|
||||
|
||||
gtk_main ();
|
||||
|
||||
return 0;
|
||||
@@ -156,3 +164,61 @@ set_up_the_evil (void)
|
||||
g_timeout_add (40, evil_timeout, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
set_up_icon_windows (void)
|
||||
{
|
||||
int i;
|
||||
int n_windows;
|
||||
|
||||
/* Create some windows */
|
||||
n_windows = 9;
|
||||
|
||||
i = 0;
|
||||
while (i < n_windows)
|
||||
{
|
||||
GtkWidget *w;
|
||||
GtkWidget *c;
|
||||
GList *icons;
|
||||
GdkPixbuf *pix;
|
||||
|
||||
w = gtk_window_new (GTK_WINDOW_TOPLEVEL);
|
||||
c = gtk_button_new_with_label ("Icon window");
|
||||
gtk_container_add (GTK_CONTAINER (w), c);
|
||||
|
||||
icons = NULL;
|
||||
|
||||
pix = gtk_widget_render_icon (w,
|
||||
GTK_STOCK_SAVE,
|
||||
GTK_ICON_SIZE_LARGE_TOOLBAR,
|
||||
NULL);
|
||||
|
||||
icons = g_list_append (icons, pix);
|
||||
|
||||
if (i % 2)
|
||||
{
|
||||
pix = gtk_widget_render_icon (w,
|
||||
GTK_STOCK_SAVE,
|
||||
GTK_ICON_SIZE_DIALOG,
|
||||
NULL);
|
||||
icons = g_list_append (icons, pix);
|
||||
}
|
||||
|
||||
if (i % 3)
|
||||
{
|
||||
pix = gtk_widget_render_icon (w,
|
||||
GTK_STOCK_SAVE,
|
||||
GTK_ICON_SIZE_MENU,
|
||||
NULL);
|
||||
icons = g_list_append (icons, pix);
|
||||
}
|
||||
|
||||
gtk_window_set_icon_list (GTK_WINDOW (w), icons);
|
||||
|
||||
g_list_foreach (icons, (GFunc) g_object_unref, NULL);
|
||||
g_list_free (icons);
|
||||
|
||||
gtk_widget_show_all (w);
|
||||
|
||||
++i;
|
||||
}
|
||||
}
|
||||
|
110
src/wm-tester/test-gravity.c
Normal file
110
src/wm-tester/test-gravity.c
Normal file
@@ -0,0 +1,110 @@
|
||||
#include <X11/Xlib.h>
|
||||
#include <X11/Xutil.h>
|
||||
#include <stdio.h>
|
||||
|
||||
int gravities[10] = {
|
||||
NorthWestGravity,
|
||||
NorthGravity,
|
||||
NorthEastGravity,
|
||||
WestGravity,
|
||||
CenterGravity,
|
||||
EastGravity,
|
||||
SouthWestGravity,
|
||||
SouthGravity,
|
||||
SouthEastGravity,
|
||||
StaticGravity
|
||||
};
|
||||
|
||||
Window windows[10];
|
||||
|
||||
int x_offset[3] = { 0, -50, -100 };
|
||||
int y_offset[3] = { 0, -50, -100 };
|
||||
double screen_x_fraction[3] = { 0, 0.5, 1.0 };
|
||||
double screen_y_fraction[3] = { 0, 0.5, 1.0 };
|
||||
int screen_width;
|
||||
int screen_height;
|
||||
|
||||
void calculate_position (int i, int *x, int *y)
|
||||
{
|
||||
if (i == 9)
|
||||
{
|
||||
*x = 150;
|
||||
*y = 150;
|
||||
}
|
||||
else
|
||||
{
|
||||
*x = screen_x_fraction[i % 3] * screen_width + x_offset[i % 3];
|
||||
*y = screen_y_fraction[i / 3] * screen_height + y_offset[i / 3];
|
||||
}
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
Display *d;
|
||||
Window w;
|
||||
XSizeHints hints;
|
||||
int i;
|
||||
int screen;
|
||||
XEvent ev;
|
||||
|
||||
d = XOpenDisplay (NULL);
|
||||
|
||||
screen = DefaultScreen (d);
|
||||
screen_width = DisplayWidth (d, screen);
|
||||
screen_height = DisplayHeight (d, screen);
|
||||
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
calculate_position (i, &x, &y);
|
||||
|
||||
w = XCreateSimpleWindow(d, RootWindow(d, screen),
|
||||
x, y, 100, 100, 0,
|
||||
WhitePixel(d, screen), WhitePixel(d, screen));
|
||||
|
||||
windows[i] = w;
|
||||
|
||||
XSelectInput (d, w, ButtonPressMask);
|
||||
|
||||
hints.flags = USPosition | PMinSize | PMaxSize | PWinGravity;
|
||||
|
||||
hints.min_width = 100;
|
||||
hints.min_height = 100;
|
||||
hints.max_width = 200;
|
||||
hints.max_height = 200;
|
||||
hints.win_gravity = gravities[i];
|
||||
|
||||
XSetWMNormalHints (d, w, &hints);
|
||||
XMapWindow (d, w);
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
XNextEvent (d, &ev);
|
||||
|
||||
if (ev.xany.type == ButtonPress)
|
||||
{
|
||||
for (i=0; i<10; i++)
|
||||
{
|
||||
if (windows[i] == ev.xbutton.window)
|
||||
{
|
||||
if (ev.xbutton.button == Button1)
|
||||
{
|
||||
int x, y;
|
||||
|
||||
calculate_position (i, &x, &y);
|
||||
w = XMoveWindow (d, windows[i], x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
w = XResizeWindow (d, windows[i], 200, 200);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
Reference in New Issue
Block a user