/* $Id: window.hg,v 1.23 2006/04/12 11:11:24 murrayc Exp $ */

/* Copyright(C) 1998-2002 The gtkmm Development Team
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License or(at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not write to the Free
 * Software Foundation Inc. 675 Mass Ave Cambridge MA 02139 USA.
 */

#include <gdkmm/drawable.h>
#include <gdkmm/bitmap.h>
//#include <gdkmm/cursor.h>
#include <gdkmm/types.h>
#include <gdkmm/region.h>
#include <gdk/gdk.h>

_DEFS(gdkmm,gdk)
_PINCLUDE(gdkmm/private/drawable_p.h)

#ifndef DOXYGEN_SHOULD_SKIP_THIS
extern "C" {
// Custom struct prototype, because this isn't what the code-generator expects:
typedef struct _GdkDrawable GdkWindow;
} // extern "C"
#endif /* DOXYGEN_SHOULD_SKIP_THIS */


namespace Gdk
{

_WRAP_ENUM(EventMask, GdkEventMask)
_WRAP_ENUM(WindowState, GdkWindowState)
_WRAP_ENUM(WindowType, GdkWindowType)
_WRAP_ENUM(WindowAttributesType, GdkWindowAttributesType)
_WRAP_ENUM(WindowHints, GdkWindowHints)
_WRAP_ENUM(WindowTypeHint, GdkWindowTypeHint)
_WRAP_ENUM(WMDecoration, GdkWMDecoration)
_WRAP_ENUM(WMFunction, GdkWMFunction)
_WRAP_ENUM(WindowEdge, GdkWindowEdge)
_WRAP_ENUM(Gravity, GdkGravity)
_WRAP_ENUM(GrabStatus, GdkGrabStatus)


class Cursor;

/** A Gdk::Window is a rectangular region on the screen. It's a low-level object, used to implement high-level objects such
 * as Gtk::Widget and Gtk::Window on the GTK+ level. A Gtk::Window is a toplevel window, the thing a user might think of as
 * a "window" with a titlebar and so on; a Gtk::Window may contain many Gdk::Windows. For example, each Gtk::Button has a
 * Gdk::Window associated with it.
 */
class Window : public Gdk::Drawable
{
  // GdkWindow is a typedef to GdkDrawable, but it's actually a GdkWindowObject.
  _CLASS_GOBJECT(Window, GdkWindow, GDK_WINDOW_OBJECT, Gdk::Drawable, GdkDrawable, GdkWindowObject)
  _STRUCT_NOT_HIDDEN
  _IGNORE(gdk_window_set_hints, gdk_window_destroy, gdk_window_new, gdk_window_get_deskrelative_origin, gdk_window_get_internal_paint_info)
  _IGNORE(gdk_window_destroy_notify, gdk_window_is_destroyed)


protected:
  Window(const Glib::RefPtr<Window>& parent, GdkWindowAttr* attributes, int attributes_mask);

public:
  _WRAP_CREATE(const Glib::RefPtr<Window>& parent, GdkWindowAttr* attributes, int attributes_mask)

  _WRAP_METHOD(WindowType get_window_type() const, gdk_window_get_window_type)
  _WRAP_METHOD(void show(), gdk_window_show)
  _WRAP_METHOD(void hide(), gdk_window_hide)
  _WRAP_METHOD(void withdraw(), gdk_window_withdraw)
  _WRAP_METHOD(void show_unraised(), gdk_window_show_unraised)
  _WRAP_METHOD(void move(int x, int y), gdk_window_move)
  _WRAP_METHOD(void resize(int width, int height), gdk_window_resize)
  _WRAP_METHOD(void move_resize(int x, int y, int width, int height), gdk_window_move_resize)
  _WRAP_METHOD(void reparent(const Glib::RefPtr<Window>& new_parent, int x, int y), gdk_window_reparent)
  _WRAP_METHOD(void clear(), gdk_window_clear)
  _WRAP_METHOD(void clear_area(int x, int y, int width, int height), gdk_window_clear_area)
  _WRAP_METHOD(void clear_area_e(int x, int y, int width, int height), gdk_window_clear_area_e)
  _WRAP_METHOD(void raise(), gdk_window_raise)
  _WRAP_METHOD(void lower(), gdk_window_lower)

  _WRAP_METHOD(void restack(const Glib::RefPtr<Window>& sibling, bool above), gdk_window_restack)

  /** Changes the position of this window in the Z-order (stacking order). This 
   * either raises (if @a above is true) or lowers the window.
   *
   * If this is a toplevel, the window manager may choose to deny the
   * request to move the window in the Z-order. restack() only
   * requests the restack but does not guarantee it.
   *
   * @param above Whether to raise or lower the window.
   *
   * @newin{2,18}
   */
  void restack(bool above);

  _WRAP_METHOD(void focus(guint32 timestamp), gdk_window_focus)
  _WRAP_METHOD(void set_user_data(gpointer user_data), gdk_window_set_user_data)
  _WRAP_METHOD(void set_override_redirect(bool override_redirect = true), gdk_window_set_override_redirect)

  //We could wrap these with a Slot instead of a C callback, but these methods are very low-level anyway.
  _WRAP_METHOD(void add_filter(GdkFilterFunc function, gpointer data), gdk_window_add_filter)
  _WRAP_METHOD(void remove_filter(GdkFilterFunc function, gpointer data), gdk_window_remove_filter)
  
  _WRAP_METHOD(void scroll(int dx, int dy), gdk_window_scroll)
  _WRAP_METHOD(void move_region(const Region& region, int dx, int dy), gdk_window_move_region)
  _WRAP_METHOD(bool ensure_native(), gdk_window_ensure_native)

  _WRAP_METHOD(void shape_combine_mask(const Glib::RefPtr<Bitmap>& mask, int x, int y), gdk_window_shape_combine_mask)
  void unset_shape_combine_mask();

  _WRAP_METHOD(void shape_combine_region(const Region& shape_region, int offset_x, int offset_y), gdk_window_shape_combine_region)
  _WRAP_METHOD(void set_child_shapes(), gdk_window_set_child_shapes)
  _WRAP_METHOD(void set_composited(bool composited = TRUE), gdk_window_set_composited)
  _WRAP_METHOD(void merge_child_shapes(), gdk_window_merge_child_shapes)

  _WRAP_METHOD(void input_shape_combine_mask(const Glib::RefPtr<Bitmap>& mask, int x, int y), gdk_window_input_shape_combine_mask)
  _WRAP_METHOD(void input_shape_combine_region (const Region& shape_region, int offset_x, int offset_y), gdk_window_input_shape_combine_region)
  _WRAP_METHOD(void set_child_input_shapes(), gdk_window_set_child_input_shapes)
  _WRAP_METHOD(void merge_child_input_shapes(), gdk_window_merge_child_input_shapes) 


  _WRAP_METHOD(bool is_visible() const, gdk_window_is_visible)
  _WRAP_METHOD(bool is_viewable() const, gdk_window_is_viewable)
  _WRAP_METHOD(WindowState get_state() const, gdk_window_get_state)
  _WRAP_METHOD(bool set_static_gravities(bool use_static = true), gdk_window_set_static_gravities)
  _WRAP_METHOD(void set_type_hint(WindowTypeHint hint), gdk_window_set_type_hint)
  _WRAP_METHOD(WindowTypeHint get_type_hint(), gdk_window_get_type_hint)
  _WRAP_METHOD(void set_modal_hint(bool modal = true), gdk_window_set_modal_hint)
  _WRAP_METHOD(void set_geometry_hints(const Geometry& geometry, WindowHints geom_mask), gdk_window_set_geometry_hints)
  _WRAP_METHOD(static void set_sm_client_id(const Glib::ustring& sm_client_id), gdk_set_sm_client_id)
  static void unset_sm_client_id();
  
  //Note: The rectangle parameter was made const in GTK+ 2.16, but we can't change that in our C++ API. TODO: Change it when we can do an ABI break.
  #m4 _CONVERSION(`Rectangle&',`const GdkRectangle*',`($3).gobj()')
  _WRAP_METHOD(void begin_paint_rect(Rectangle& rectangle), gdk_window_begin_paint_rect)
  _WRAP_METHOD(void begin_paint_region(const Region& region), gdk_window_begin_paint_region)
  _WRAP_METHOD(void end_paint(), gdk_window_end_paint)
  _WRAP_METHOD(void set_title(const Glib::ustring& title), gdk_window_set_title)
  _WRAP_METHOD(void set_role(const Glib::ustring& role), gdk_window_set_role)
  _WRAP_METHOD(void set_startup_id(const Glib::ustring& startup_id), gdk_window_set_startup_id)
  _WRAP_METHOD(void set_transient_for(const Glib::RefPtr<Window>& parent), gdk_window_set_transient_for)
  _WRAP_METHOD(void set_background(const Color& color), gdk_window_set_background)
  _WRAP_METHOD(void set_back_pixmap(const Glib::RefPtr<Pixmap>&pixmap, bool parent_relative = true), gdk_window_set_back_pixmap)

  /** Unsets the background pixmap of @a window so that the window will have no
   * background.  A window with no background will never have its
   * background filled by the windowing system, instead the window will
   * contain whatever pixels were already in the corresponding area of
   * the display.
   *
   * @see set_back_pixmap().
   * @newin{2,14}
   */
  void unset_back_pixmap();

#m4 _CONVERSION(const Cursor&,GdkCursor*,const_cast<GdkCursor*>(($3).gobj()))
  _WRAP_METHOD(void set_cursor(const Cursor& cursor), gdk_window_set_cursor)
  
  /** Use the parent window's cursor.
   * For top-level windows this means that it will use the default cursor for the ROOT window.
   */
  void set_cursor();

  //TODO:_WRAP_METHOD(Cursor get_cursor(), gdk_window_get_cursor)
  
  _WRAP_METHOD(void get_user_data(gpointer* data), gdk_window_get_user_data)
  _WRAP_METHOD(void get_geometry(int& x, int& y, int& width, int& height, int& depth) const, gdk_window_get_geometry)
  _WRAP_METHOD(void get_position(int& x, int& y) const, gdk_window_get_position)
  _WRAP_METHOD(int get_origin(int& x, int& y) const, gdk_window_get_origin)
  _WRAP_METHOD(void get_root_coords(int x, int y, int& root_x, int& root_y), gdk_window_get_root_coords)
  _IGNORE(gdk_window_get_deskrelative_origin)
  _WRAP_METHOD(void get_root_origin(int& x, int& y) const, gdk_window_get_root_origin)
  _WRAP_METHOD(void get_frame_extents(Rectangle& rect), gdk_window_get_frame_extents)
  _WRAP_METHOD(Glib::RefPtr<Window> get_pointer(int& x, int& y, ModifierType& mask), gdk_window_get_pointer, refreturn)
  _WRAP_METHOD(Glib::RefPtr<Window> get_parent(), gdk_window_get_parent, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Window> get_parent() const, gdk_window_get_parent, refreturn, constversion)
  _WRAP_METHOD(Glib::RefPtr<Window> get_toplevel(), gdk_window_get_toplevel, refreturn)
  _WRAP_METHOD(Glib::RefPtr<const Window> get_toplevel() const, gdk_window_get_toplevel, refreturn, constversion)
  
  _WRAP_METHOD(Glib::ListHandle< Glib::RefPtr<Window> > get_children(), gdk_window_get_children)
  _WRAP_METHOD(Glib::ListHandle< Glib::RefPtr<const Window> > get_children() const, gdk_window_get_children)
  _IGNORE(gdk_window_peek_children) //gdk_window_peek_children() is the same as gdk_window_get_children() with different memory mangement of the list.

  _WRAP_METHOD(EventMask get_events() const, gdk_window_get_events)
  _WRAP_METHOD(void set_events(EventMask event_mask), gdk_window_set_events)

  _WRAP_METHOD(void set_icon_list(const Glib::ListHandle< Glib::RefPtr<Gdk::Pixbuf> >& pixbufs), gdk_window_set_icon_list)
  _WRAP_METHOD(void set_icon(const Glib::RefPtr<Window>& icon_window, const Glib::RefPtr<Pixmap>& pixmap, const Glib::RefPtr<Bitmap>& mask), gdk_window_set_icon)
  void set_icon(const Glib::RefPtr<Window>& icon_window, const Glib::RefPtr<Pixmap>& pixmap);
  void unset_icon();
  _WRAP_METHOD(void set_icon_name(const Glib::ustring& name), gdk_window_set_icon_name)

  _WRAP_METHOD(void set_group(const Glib::RefPtr<Window>& leader), gdk_window_set_group)  
  _WRAP_METHOD(Glib::RefPtr<Window> get_group(), gdk_window_get_group)
  _WRAP_METHOD(Glib::RefPtr<const Window> get_group() const, gdk_window_get_group, constversion)

  _WRAP_METHOD(void set_decorations(WMDecoration decorations), gdk_window_set_decorations)
  _WRAP_METHOD(bool get_decorations(WMDecoration& decorations) const, gdk_window_get_decorations)
  _WRAP_METHOD(void set_functions(WMFunction functions), gdk_window_set_functions)
  
  _WRAP_METHOD(static Glib::ListHandle< Glib::RefPtr<Window> > get_toplevels(), gdk_window_get_toplevels)
    
  _WRAP_METHOD(void beep(), gdk_window_beep)

  _WRAP_METHOD(void iconify(), gdk_window_iconify)
  _WRAP_METHOD(void deiconify(), gdk_window_deiconify)
  _WRAP_METHOD(void stick(), gdk_window_stick)
  _WRAP_METHOD(void unstick(), gdk_window_unstick)
  _WRAP_METHOD(void maximize(), gdk_window_maximize)
  _WRAP_METHOD(void unmaximize(), gdk_window_unmaximize)
  _WRAP_METHOD(void register_dnd(), gdk_window_register_dnd)
  _WRAP_METHOD(void begin_resize_drag(WindowEdge  edge, int button, int root_x, int root_y, guint32 timestamp), gdk_window_begin_resize_drag)
  _WRAP_METHOD(void begin_move_drag(int button, int root_x, int root_y, guint32 timestamp), gdk_window_begin_move_drag)

  _WRAP_METHOD(void invalidate_rect(const Rectangle& rect, bool invalidate_children), gdk_window_invalidate_rect)

  /** A convenience wrapper around invalidate_region() which
   * invalidates the whole region. See invalidate_region() for details.
   * @param invalidate_children Whether to also invalidate child windows.
   */
  void invalidate(bool invalidate_children);

  _WRAP_METHOD(void invalidate_region(const Region& region, bool invalidate_children = true), gdk_window_invalidate_region)

  _WRAP_METHOD(Region get_update_area(), gdk_window_get_update_area)
  //This method should not have a const version - see the docs.
  
  _WRAP_METHOD(void freeze_updates(), gdk_window_freeze_updates)
  _WRAP_METHOD(void thaw_updates(), gdk_window_thaw_updates)
  _WRAP_METHOD(static void process_all_updates(), gdk_window_process_all_updates)
  _WRAP_METHOD(void process_updates(bool update_children), gdk_window_process_updates)
  _WRAP_METHOD(static void set_debug_updates(bool setting = true), gdk_window_set_debug_updates)
  _WRAP_METHOD(static void constrain_size(const Geometry& geometry, guint flags, int width, int height, int& new_width, int& new_height), gdk_window_constrain_size)
  void get_internal_paint_info(Glib::RefPtr<Drawable>& real_drawable, int& x_offset, int& y_offset) const;
  
  _WRAP_METHOD(void enable_synchronized_configure(), gdk_window_enable_synchronized_configure)
  _WRAP_METHOD(void configure_finished(), gdk_window_configure_finished)

  _WRAP_METHOD(void set_skip_taskbar_hint(bool skips_taskbar = true), gdk_window_set_skip_taskbar_hint)
  _WRAP_METHOD(void set_skip_pager_hint(bool skips_pager = true), gdk_window_set_skip_pager_hint)

  _WRAP_METHOD(void set_urgency_hint(bool urgent = true), gdk_window_set_urgency_hint)

  _WRAP_METHOD(void fullscreen(), gdk_window_fullscreen)
  _WRAP_METHOD(void unfullscreen(), gdk_window_unfullscreen)

  _WRAP_METHOD(GrabStatus pointer_grab(bool owner_events, EventMask event_mask, const Glib::RefPtr<const Window>& confine_to, const Cursor& cursor, guint32 time_), gdk_pointer_grab)

  /** Grabs the pointer to a specific window.
   * Requires a corresponding call to pointer_ungrab().
   *
   * Arguments:
   * @param owner_events Specifies whether events will be reported as is, or relative to the window.
   * @param event_mask Masks only interesting events.
   * @param cursor Changes the cursor for the duration of the grab.
   * @param timestamp Specifies the time.
   */
  GrabStatus pointer_grab(bool owner_events, EventMask event_mask, const Cursor& cursor, guint32 timestamp);

  /** Grabs the pointer to a specific window.
   * Requires a corresponding call to pointer_ungrab().
   *
   * Arguments:
   * @param owner_events Specifies whether events will be reported as is, or relative to the window.
   * @param event_mask Masks only interesting events.
   * @param timestamp Specifies the time.
   */
  GrabStatus pointer_grab(bool owner_events, EventMask event_mask, guint32 timestamp);

  _WRAP_METHOD(static void pointer_ungrab(guint32 timestamp), gdk_pointer_ungrab)
  _WRAP_METHOD(GrabStatus keyboard_grab(bool owner_events, guint32 timestamp), gdk_keyboard_grab)
  _WRAP_METHOD(static void keyboard_ungrab(guint32 timestamp), gdk_keyboard_ungrab)

  _WRAP_METHOD(void set_keep_above(bool setting = true), gdk_window_set_keep_above)
  _WRAP_METHOD(void set_keep_below(bool setting = true), gdk_window_set_keep_below)

  _WRAP_METHOD(void set_opacity(double opacity), gdk_window_set_opacity)

  _WRAP_METHOD(void set_accept_focus(bool accept_focus = true), gdk_window_set_accept_focus)
  
  _WRAP_METHOD(void set_focus_on_map(bool focus_on_map), gdk_window_set_focus_on_map)

  _WRAP_METHOD(static Glib::RefPtr<Window> get_default_root_window(), gdk_get_default_root_window)

//TODO: Wrap these?
/*
GdkPixmap *gdk_offscreen_window_get_pixmap     (GdkWindow     *window);
void       gdk_offscreen_window_set_embedder   (GdkWindow     *window,
						GdkWindow     *embedder);
GdkWindow *gdk_offscreen_window_get_embedder   (GdkWindow     *window);
*/

  _WRAP_METHOD(void redirect_to_drawable(const Glib::RefPtr<Drawable>& drawable, int src_x, int src_y, int dest_x, int dest_y, int width, int height), gdk_window_redirect_to_drawable)
  _WRAP_METHOD(void remove_redirection(), gdk_window_remove_redirection)

  _WRAP_METHOD(void geometry_changed(), gdk_window_geometry_changed)
};

} /* namespace Gdk */

