Compare commits

..

69 Commits

Author SHA1 Message Date
Havoc Pennington
e8bc8e95e2 add bad hack to work with GTK 1.3.9.90 RPMs from gnomehide for now
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 04:15:25 +00:00
Havoc Pennington
cfd3cdd64e bump version
2001-10-13  Havoc Pennington  <hp@redhat.com>

	* configure.in: bump version
2001-10-13 04:03:56 +00:00
Havoc Pennington
ec4edcb78c hmm, fix build
2001-10-13  Havoc Pennington  <hp@pobox.com>

	* src/session.c (meta_session_init): hmm, fix build
2001-10-13 04:02:59 +00:00
Havoc Pennington
94c3b02eef makefile tweak, add a comment to frame.c 2001-10-13 04:00:08 +00:00
Havoc Pennington
f83ac8476c set the session manager priority so we start up before other apps.
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 04:52:53 +00:00
Mikael Hallendal
4edccc4eb5 use gdk_pixbuf_new_from_inline (meta_ui_get_default_mini_icon): use
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-12 00:20:02 +00:00
Christian Rose
0398a78b4a Fixed some typos. Thanks to Tomas gren <stric@ing.umu.se> for spotting
2001-10-11  Christian Rose  <menthos@menthos.com>

	* sv.po: Fixed some typos. Thanks to Tomas gren <stric@ing.umu.se>
	for spotting many of them.
2001-10-11 11:05:30 +00:00
Christian Rose
ec6a455fb0 Added "sv" to ALL_LINGUAS. Added Swedish translation. Added files. Added
2001-10-11  Christian Rose  <menthos@menthos.com>

	* configure.in: Added "sv" to ALL_LINGUAS.
	* po/sv.po: Added Swedish translation.
	* po/POTFILES.in: Added files.
	* po/.cvsignore: Added messages and *.pot.
2001-10-11 08:40:04 +00:00
Havoc Pennington
e55ead0419 fix mem leak of the MetaStack object (meta_stack_sync_to_server): try to
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-11 01:29:20 +00:00
Havoc Pennington
f22b9dfd94 set _NET_ACTIVE_WINDOW hint
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 23:06:19 +00:00
Havoc Pennington
ec4dfd0cbc don't allow shade/maximize/minimize for windows that don't support those
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-07 22:11:13 +00:00
Havoc Pennington
350ecb1dcf add code to grab all modifier combinations, so keybindings work with
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-10-05 02:58:48 +00:00
Alex Graveley
38a878171a Add inlinepixbufs.h so that it gets generated.
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-21 19:20:56 +00:00
Havoc Pennington
dad1b107f5 add hackaround for the warning about gtk-menu-bar-accel
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-18 03:40:03 +00:00
Havoc Pennington
582a80f518 ref the returned icon, oops.
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 05:50:02 +00:00
Havoc Pennington
808d21e857 tiny update 2001-09-17 04:47:36 +00:00
Havoc Pennington
0a1f2b3a47 fix srcdir != builddir glitch
2001-09-17  Havoc Pennington  <hp@pobox.com>

	* src/Makefile.am (VARIABLES): fix srcdir != builddir glitch
2001-09-17 04:45:13 +00:00
Havoc Pennington
4c104e1cb7 use the inline image data for default icon
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-17 04:42:37 +00:00
Havoc Pennington
ecf75915c7 disconnect this callback on error
2001-09-16  Havoc Pennington  <hp@pobox.com>

	* src/session.c (process_ice_messages): disconnect this callback
	on error
2001-09-17 04:11:25 +00:00
Havoc Pennington
7be4c63ee4 new function
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-16 21:50:27 +00:00
Havoc Pennington
b09a781a80 remove msm from here, now in its own module 2001-09-16 20:43:45 +00:00
Havoc Pennington
52dc32031d ... 2001-09-16 03:47:05 +00:00
Havoc Pennington
a926a4a0ca ... 2001-09-16 02:52:23 +00:00
Havoc Pennington
39df21227d add support for a mini icon in the titlebar (update_icon): re-enable
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-16 00:30:45 +00:00
Havoc Pennington
2830c9d748 ... 2001-09-15 02:37:02 +00:00
Havoc Pennington
3886f0ecac ... 2001-09-14 14:25:24 +00:00
Havoc Pennington
b1c7811e89 ... 2001-09-14 06:30:50 +00:00
Havoc Pennington
1385d192c5 stuff 2001-09-13 05:00:50 +00:00
Havoc Pennington
82aa7363f9 still does not work. 2001-09-13 04:50:18 +00:00
Havoc Pennington
a4346200e8 does not work. 2001-09-12 06:06:08 +00:00
Havoc Pennington
9f66f63bf5 fix up handling of text properties, so we get UTF8_STRING as that type and
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-11 04:37:10 +00:00
Havoc Pennington
3645fef5e0 icon for unmaximize
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-11 03:54:54 +00:00
Havoc Pennington
f386494ba4 Don't separate user_has_moved/user_has_resized, fixes bug in east-resizing
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-11 02:57:05 +00:00
Havoc Pennington
936adc6ea5 don't use gdk_display_name
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-09 03:44:42 +00:00
Havoc Pennington
bc787fc1f3 bump version 2.3.5, require newer GTK release
2001-09-06  Havoc Pennington  <hp@pobox.com>

	* configure.in: bump version 2.3.5, require newer GTK release
2001-09-06 04:40:03 +00:00
Havoc Pennington
1c6c7350e1 make test apps noinst
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-05 03:57:45 +00:00
Havoc Pennington
2a0a5dfdf8 clean up the code, and replace GDK X error handler with one that chains up
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-09-01 05:53:07 +00:00
Havoc Pennington
501dd26713 fix args to gtk_alignment_new()
2001-08-31  Havoc Pennington  <hp@pobox.com>

	* src/tabpopup.c (meta_ui_tab_popup_new): fix args to
	gtk_alignment_new()
2001-08-31 06:13:07 +00:00
Havoc Pennington
3e1c68b88a avoid focusing a window on tab popup popdown
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-30 04:01:38 +00:00
Havoc Pennington
6d31d4756e Switch back to outline.
2001-08-29  Havoc Pennington  <hp@redhat.com>

	* src/tabpopup.c: Switch back to outline.
2001-08-29 16:38:57 +00:00
Havoc Pennington
bea9d1f679 experiment with window-cover-with-icon instead of just the outline; can't
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 05:07:39 +00:00
Havoc Pennington
4abbd4b1e5 add crackrock window-outlining feature
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 04:53:48 +00:00
Havoc Pennington
27c81cad33 wrong atom name - _NET_SUPPORTED not _NET_WM_SUPPORTED
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-29 04:16:30 +00:00
Havoc Pennington
db0a7e2978 Unbreak tab popup a bit.
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-29 03:37:03 +00:00
Havoc Pennington
4d2f018ddb force fullscreen windows to be at 0,0
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-26 02:09:53 +00:00
Havoc Pennington
5eb43d34ff attempt to use the mask as well as the pixmap. Probably doesn't work so
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-24 00:32:17 +00:00
Havoc Pennington
ddfffe270f make this look a little nicer
2001-08-22  Havoc Pennington  <hp@pobox.com>

	* src/tabpopup.c: make this look a little nicer
2001-08-23 03:24:51 +00:00
Havoc Pennington
cebbafdd22 put in a FIXME 2001-08-22 22:12:44 +00:00
Havoc Pennington
46082f8c71 all the MWM flag tests were backward
2001-08-22  Havoc Pennington  <hp@pobox.com>

	* src/window.c (update_mwm_hints): all the MWM flag tests were
	backward
2001-08-22 06:53:33 +00:00
Havoc Pennington
e51c12d1cd half-ass implementation of getting pixmap icons (WM_NORMAL_HINTS and
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-22 06:01:01 +00:00
Havoc Pennington
f562e65d5f add a "fullscreen" semantic type; if a window requests the screen size
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-20 03:17:40 +00:00
Havoc Pennington
04e09d4c56 we support _NET_WM_ICON
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-20 01:42:44 +00:00
Havoc Pennington
78a68f3e10 note about bug in tab focusing 2001-08-19 18:26:15 +00:00
Havoc Pennington
b2444df787 remove XSync, error traps already do that
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 18:09:10 +00:00
Havoc Pennington
f70993be97 add prototype thingy to display windows we're cycling through with tab.
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-19 06:23:59 +00:00
Havoc Pennington
92a965b979 Make a half-hearted not-very-tested attempt to handle window resizes
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-19 02:45:55 +00:00
Havoc Pennington
922749e5b3 hrm, I fixed this wrong the other day. Fixes static gravity when moving
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-19 02:29:38 +00:00
Havoc Pennington
9acaa50f59 oops, accidentally turned on opaque iconify 2001-08-19 02:00:26 +00:00
Havoc Pennington
60f531af35 also set the current size. Lame hack of the day.
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 scren 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-19 01:58:00 +00:00
Havoc Pennington
246ac5e578 use the delay exposes feature to avoid the scren dirt
2001-08-18  Havoc Pennington  <hp@pobox.com>

	* src/effects.c (effects_draw_box_animation_timeout): use the
	delay exposes feature to avoid the scren dirt

	* src/ui.c (meta_image_window_set_position): use gtk_window_move()
	to set the position
	(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-19 01:19:54 +00:00
Havoc Pennington
505282697a fix for StaticGravity
2001-08-17  Havoc Pennington  <hp@redhat.com>

	* src/window.c (meta_window_get_gravity_position): fix for
	StaticGravity
2001-08-17 22:44:36 +00:00
Havoc Pennington
6768aefb9d Honor USPosition even post-map. I know I'll regret this.
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-10 03:32:45 +00:00
Havoc Pennington
fc8db63716 set _NET_WM_NAME hint as a UTF8_STRING not STRING. Patch from Anders.
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-07 05:52:51 +00:00
Havoc Pennington
d6bf2f5e80 disable opaque animations by default, current implementation suXors.
2001-08-06  Havoc Pennington  <hp@redhat.com>

	* src/effects.c: disable opaque animations by default, current
	implementation suXors.
2001-08-06 18:28:51 +00:00
Havoc Pennington
8c7b04edb9 Get start time after we do the pixbuf from drawable, so we don't count
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 08:03:48 +00:00
Havoc Pennington
11b14d327f add opaque minimize/shade feature. The wireframe seemed kind of confusing
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-06 07:58:49 +00:00
Havoc Pennington
d8561cb4c3 modify to be smoother (at least theoretically) by syncing to current time
2001-08-06  Havoc Pennington  <hp@pobox.com>

	* 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. A precursor to flashier animations
	that take more CPU to do.

	* src/window.c (meta_window_shade): draw animation
	for shading too
2001-08-06 05:12:22 +00:00
Havoc Pennington
47ce823aa5 draw animation for shading too
2001-08-06  Havoc Pennington  <hp@pobox.com>

	* src/window.c (meta_window_shade): draw animation
	for shading too
2001-08-06 04:43:31 +00:00
Anders Carlsson
971419c880 Add _NET_WM_ICON_GEOMETRY atom.
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-05 16:04:52 +00:00
42 changed files with 4943 additions and 692 deletions

421
ChangeLog
View File

@@ -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

View File

@@ -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
View File

@@ -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.

View File

@@ -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
])

View File

@@ -4,3 +4,5 @@ Makefile.in
Makefile
stamp-cat-id
cat-id-tbl.c
messages
*.pot

11
po/ChangeLog Normal file
View 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.

View File

@@ -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
View 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"

View File

@@ -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)

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

Binary file not shown.

After

Width:  |  Height:  |  Size: 424 B

View File

@@ -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;
}
}

View File

@@ -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
View 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 (&current_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
View 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 */

View File

@@ -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;
}

View File

@@ -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,

View File

@@ -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);
}
}

View File

@@ -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

View File

@@ -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)
{

View File

@@ -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);

View File

@@ -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
View File

@@ -0,0 +1,6 @@
[Desktop Entry]
Name=Metacity
Exec=metacity
[Window Manager]
SessionManaged=true

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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 */
}

View File

@@ -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

View File

@@ -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);

View File

@@ -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

View File

@@ -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
View 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
View 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
View File

@@ -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;
}

View File

@@ -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

View File

@@ -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");

File diff suppressed because it is too large Load Diff

View File

@@ -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 */

View File

@@ -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@

View File

@@ -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;
}
}

View 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;
}