indexing

	description: "[

		Eiffel Vision drawing area. Implementation of the interface for Linux.

	]"
	date: "$Date$"
	revision: "$Revision$"

class
	EM_EV_WIDGET_IMP

inherit
	EM_EV_WIDGET_I
		undefine
			default_create
		redefine
			interface
		end

	EV_PRIMITIVE_IMP
		undefine
			copy,
			initialize
		redefine
			interface,
			set_focus
		end

	EM_VIDEO_FUNCTIONS_EXTERNAL
		export {NONE} all end

	KL_SHARED_EXECUTION_ENVIRONMENT
		export {NONE} all end

create
	make

feature {NONE} -- Initialization

	make (an_interface: like interface) is
			-- Create an EiffelMedia widget.
		local
			em_intermediary: EV_INTERMEDIARY_ROUTINES
		do
			base_make (an_interface)
			set_c_object ({EV_GTK_EXTERNALS}.gtk_drawing_area_new)

			create em_intermediary

			if {EV_GTK_EXTERNALS}.gtk_is_window (c_object) then
				real_signal_connect (c_object, "configure-event", agent (em_intermediary).on_size_allocate_intermediate (internal_id, ?, ?, ?, ?), size_allocate_translate_agent)
			else
				real_signal_connect (c_object, "size-allocate", agent (em_intermediary).on_size_allocate_intermediate (internal_id, ?, ?, ?, ?), size_allocate_translate_agent)
			end

			real_signal_connect (c_object, "expose_event", agent redraw , App_implementation.Default_translate)
			real_signal_connect (c_object, "button-press-event", agent get_focus, App_implementation.Default_translate)
		end

	initialize is
			-- Initialize `Current'.
		do
			{EV_GTK_DEPENDENT_EXTERNALS}.gtk_widget_set_redraw_on_allocate (c_object, False)
				-- This means that when the drawing area is resized, only the new portions are redrawn

			{EV_GTK_EXTERNALS}.gtk_widget_set_double_buffered (c_object, False)
			Precursor {EV_PRIMITIVE_IMP}
		end

feature -- widget handling

	redraw is
			-- Redraw the content of the EiffelMedia widget
		do
			if interface.screen /= Void then
				interface.screen.redraw
			end
		end

	get_focus is
			-- Gets the focus back
		do
			lose_focus
			set_focus
		end		

	em_prepare is
			-- Prepare Window for EiffelMedia
		local
			window: POINTER
			window_id: INTEGER
			env_var: STRING
			
			success: BOOLEAN
		do
			{EV_GTK_EXTERNALS}.gtk_widget_realize (c_object)
			
			-- in this loop we simply wait as long as necessary to get a valid
			-- window id.
			from 
			until
				success
			loop
				window := {EV_GTK_EXTERNALS}.gtk_widget_struct_window (c_object)
				window_id := get_gdk_window_xwindow_external (window)
				
				if window_id = 0 then
					success := false
					usleep (500000)
				else
					success := true
				end
			end
			
			env_var := window_id.out
			Execution_environment.set_variable_value ("SDL_WINDOWID", env_var)
		end

feature -- focus handling

	lose_focus is
		do
			{EV_GTK_EXTERNALS}.gtk_widget_unset_flags (c_object, {EV_GTK_EXTERNALS}.gtk_can_focus_enum)
				-- This is a hack to make sure focus flag is unset.
		end

	set_focus is
			-- Grab keyboard focus.
		do
			if not has_focus then
				{EV_GTK_EXTERNALS}.gtk_widget_set_flags (c_object, {EV_GTK_EXTERNALS}.gtk_can_focus_enum)

				if focus_in_actions_internal /= Void then
					focus_in_actions_internal.block
					-- This needs to be called manually for cases that gtk doesn't handle.
				end
				{EV_GTK_EXTERNALS}.gtk_widget_grab_focus (c_object)

				{EV_GTK_EXTERNALS}.gtk_widget_set_flags (c_object, {EV_GTK_EXTERNALS}.GTK_HAS_FOCUS_ENUM)

				{EV_GTK_EXTERNALS}.gtk_widget_unset_flags (c_object, {EV_GTK_EXTERNALS}.GTK_CAN_FOCUS_ENUM)

				if focus_in_actions_internal /= Void then
					focus_in_actions_internal.resume
					focus_in_actions_internal.call (Void)
				end
			end
		end
		
feature {NONE} -- External implementation

	usleep (micro_seconds: INTEGER) is
		external
			"C | <unistd.h>"
		end

feature {NONE} -- Implementation

	interface: EM_EV_WIDGET
			-- Responsible for interaction with the underlying native graphics
			-- toolkit.
end