1 ///////////////////////////////////////////////////////////////////////////// 
   2 // Name:        src/gtk/minifram.cpp 
   4 // Author:      Robert Roebling 
   6 // Copyright:   (c) 1998 Robert Roebling 
   7 // Licence:     wxWindows licence 
   8 ///////////////////////////////////////////////////////////////////////////// 
  10 // For compilers that support precompilation, includes "wx.h". 
  11 #include "wx/wxprec.h" 
  15 #include "wx/minifram.h" 
  18     #include "wx/dcscreen.h" 
  22 #include "wx/gtk/win_gtk.h" 
  23 #include "wx/gtk/private.h" 
  26 #include <gdk/gdkprivate.h> 
  29 //----------------------------------------------------------------------------- 
  31 //----------------------------------------------------------------------------- 
  33 extern bool        g_blockEventsOnDrag
; 
  34 extern bool        g_blockEventsOnScroll
; 
  35 extern GtkWidget  
*wxGetRootWindow(); 
  37 //----------------------------------------------------------------------------- 
  39 //----------------------------------------------------------------------------- 
  41 /* draw XOR rectangle when moving mine frame around */ 
  43 static void DrawFrame( GtkWidget 
*widget
, int x
, int y
, int w
, int h 
) 
  47     gdk_window_get_origin( widget
->window
, &org_x
, &org_y 
); 
  51     GdkGC 
*gc 
= gdk_gc_new( gdk_get_default_root_window() ); 
  52     gdk_gc_set_subwindow( gc
, GDK_INCLUDE_INFERIORS 
); 
  53     gdk_gc_set_function( gc
, GDK_INVERT 
); 
  55     gdk_draw_rectangle( gdk_get_default_root_window(), gc
, FALSE
, x
, y
, w
, h 
); 
  59 //----------------------------------------------------------------------------- 
  60 // "expose_event" of m_mainWidget 
  61 //----------------------------------------------------------------------------- 
  64 static void gtk_window_own_expose_callback( GtkWidget 
*widget
, GdkEventExpose 
*gdk_event
, wxFrame 
*win 
) 
  66     if (g_isIdle
) wxapp_install_idle_handler(); 
  68     if (!win
->m_hasVMT
) return; 
  69     if (gdk_event
->count 
> 0) return; 
  71     GtkPizza 
*pizza 
= GTK_PIZZA(widget
); 
  73     gtk_paint_shadow (widget
->style
, 
  77                       NULL
, NULL
, NULL
, // FIXME: No clipping? 
  79                       win
->m_width
, win
->m_height
); 
  81     if (!win
->GetTitle().empty() && 
  82         ((win
->GetWindowStyle() & wxCAPTION
) || 
  83          (win
->GetWindowStyle() & wxTINY_CAPTION_HORIZ
) || 
  84          (win
->GetWindowStyle() & wxTINY_CAPTION_VERT
))) 
  87         dc
.SetFont( *wxSMALL_FONT 
); 
  88         int height 
= dc
.GetCharHeight(); 
  90         GdkGC 
*gc 
= gdk_gc_new( pizza
->bin_window 
); 
  91         gdk_gc_set_foreground( gc
, &widget
->style
->bg
[GTK_STATE_SELECTED
] ); 
  92         gdk_draw_rectangle( pizza
->bin_window
, gc
, TRUE
, 
 100         dc
.m_window 
= pizza
->bin_window
; 
 101         dc
.SetTextForeground( *wxWHITE 
); 
 102         dc
.DrawText( win
->GetTitle(), 6, 3 ); 
 107 //----------------------------------------------------------------------------- 
 108 // "button_press_event" of m_mainWidget 
 109 //----------------------------------------------------------------------------- 
 112 static gint 
gtk_window_button_press_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxMiniFrame 
*win 
) 
 114     if (g_isIdle
) wxapp_install_idle_handler(); 
 116     if (!win
->m_hasVMT
) return FALSE
; 
 117     if (g_blockEventsOnDrag
) return TRUE
; 
 118     if (g_blockEventsOnScroll
) return TRUE
; 
 120     if (win
->m_isDragging
) return TRUE
; 
 122     GtkPizza 
*pizza 
= GTK_PIZZA(widget
); 
 123     if (gdk_event
->window 
!= pizza
->bin_window
) return TRUE
; 
 126     dc
.SetFont( *wxSMALL_FONT 
); 
 127     int height 
= dc
.GetCharHeight() + 1; 
 129     if (gdk_event
->y 
> height
) return TRUE
; 
 131     gdk_window_raise( win
->m_widget
->window 
); 
 133     gdk_pointer_grab( widget
->window
, FALSE
, 
 135                          (GDK_BUTTON_PRESS_MASK 
| 
 136                           GDK_BUTTON_RELEASE_MASK 
| 
 137                           GDK_POINTER_MOTION_MASK        
| 
 138                           GDK_POINTER_MOTION_HINT_MASK  
| 
 139                           GDK_BUTTON_MOTION_MASK        
| 
 140                           GDK_BUTTON1_MOTION_MASK
), 
 143                       (unsigned int) GDK_CURRENT_TIME 
); 
 145     win
->m_diffX 
= (int)gdk_event
->x
; 
 146     win
->m_diffY 
= (int)gdk_event
->y
; 
 147     DrawFrame( widget
, 0, 0, win
->m_width
, win
->m_height 
); 
 151     win
->m_isDragging 
= true; 
 157 //----------------------------------------------------------------------------- 
 158 // "button_release_event" of m_mainWidget 
 159 //----------------------------------------------------------------------------- 
 162 static gint 
gtk_window_button_release_callback( GtkWidget 
*widget
, GdkEventButton 
*gdk_event
, wxMiniFrame 
*win 
) 
 164     if (g_isIdle
) wxapp_install_idle_handler(); 
 166     if (!win
->m_hasVMT
) return FALSE
; 
 167     if (g_blockEventsOnDrag
) return TRUE
; 
 168     if (g_blockEventsOnScroll
) return TRUE
; 
 170     if (!win
->m_isDragging
) return TRUE
; 
 172     win
->m_isDragging 
= false; 
 174     int x 
= (int)gdk_event
->x
; 
 175     int y 
= (int)gdk_event
->y
; 
 177     DrawFrame( widget
, win
->m_oldX
, win
->m_oldY
, win
->m_width
, win
->m_height 
); 
 178     gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME 
); 
 181     gdk_window_get_origin( widget
->window
, &org_x
, &org_y 
); 
 182     x 
+= org_x 
- win
->m_diffX
; 
 183     y 
+= org_y 
- win
->m_diffY
; 
 186     gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y 
); 
 192 //----------------------------------------------------------------------------- 
 193 // "motion_notify_event" of m_mainWidget 
 194 //----------------------------------------------------------------------------- 
 197 static gint 
gtk_window_motion_notify_callback( GtkWidget 
*widget
, GdkEventMotion 
*gdk_event
, wxMiniFrame 
*win 
) 
 199     if (g_isIdle
) wxapp_install_idle_handler(); 
 201     if (!win
->m_hasVMT
) return FALSE
; 
 202     if (g_blockEventsOnDrag
) return TRUE
; 
 203     if (g_blockEventsOnScroll
) return TRUE
; 
 205     if (!win
->m_isDragging
) return TRUE
; 
 207     if (gdk_event
->is_hint
) 
 211        GdkModifierType state
; 
 212        gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
); 
 215        gdk_event
->state 
= state
; 
 218     DrawFrame( widget
, win
->m_oldX
, win
->m_oldY
, win
->m_width
, win
->m_height 
); 
 219     win
->m_oldX 
= (int)gdk_event
->x 
- win
->m_diffX
; 
 220     win
->m_oldY 
= (int)gdk_event
->y 
- win
->m_diffY
; 
 221     DrawFrame( widget
, win
->m_oldX
, win
->m_oldY
, win
->m_width
, win
->m_height 
); 
 227 //----------------------------------------------------------------------------- 
 228 // "clicked" of X system button 
 229 //----------------------------------------------------------------------------- 
 232 static void gtk_button_clicked_callback( GtkWidget 
*WXUNUSED(widget
), wxMiniFrame 
*mf 
) 
 234     if (g_isIdle
) wxapp_install_idle_handler(); 
 240 //----------------------------------------------------------------------------- 
 242 //----------------------------------------------------------------------------- 
 244 static const char *cross_xpm
[] = { 
 245 /* columns rows colors chars-per-pixel */ 
 257 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
) 
 259 bool wxMiniFrame::Create( wxWindow 
*parent
, wxWindowID id
, const wxString 
&title
, 
 260       const wxPoint 
&pos
, const wxSize 
&size
, 
 261       long style
, const wxString 
&name 
) 
 263     style 
= style 
| wxCAPTION
; 
 265     if ((style 
& wxCAPTION
) || (style 
& wxTINY_CAPTION_HORIZ
) || (style 
& wxTINY_CAPTION_VERT
)) 
 269     m_isDragging 
= false; 
 275     wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name 
); 
 277     if (m_parent 
&& (GTK_IS_WINDOW(m_parent
->m_widget
))) 
 279         gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) ); 
 282     if ((style 
& wxSYSTEM_MENU
) && 
 283         ((style 
& wxCAPTION
) || (style 
& wxTINY_CAPTION_HORIZ
) || (style 
& wxTINY_CAPTION_VERT
))) 
 285         GdkBitmap 
*mask 
= (GdkBitmap
*) NULL
; 
 286         GdkPixmap 
*pixmap 
= gdk_pixmap_create_from_xpm_d
 
 288                                 wxGetRootWindow()->window
, 
 294         GtkWidget 
*pw 
= gtk_pixmap_new( pixmap
, mask 
); 
 295         g_object_unref (mask
); 
 296         g_object_unref (pixmap
); 
 297         gtk_widget_show( pw 
); 
 299         GtkWidget 
*close_button 
= gtk_button_new(); 
 301         if (!gtk_check_version(2,4,0)) 
 302             gtk_button_set_focus_on_click( GTK_BUTTON(close_button
), FALSE 
); 
 304         gtk_container_add( GTK_CONTAINER(close_button
), pw 
); 
 306         gtk_pizza_put( GTK_PIZZA(m_mainWidget
), 
 308                          size
.x
-16, 4, 11, 11 ); 
 310         gtk_widget_show( close_button 
); 
 312         g_signal_connect (close_button
, "clicked", 
 313                           G_CALLBACK (gtk_button_clicked_callback
), 
 317     /* these are called when the borders are drawn */ 
 318     g_signal_connect (m_mainWidget
, "expose_event", 
 319                       G_CALLBACK (gtk_window_own_expose_callback
), this ); 
 321     /* these are required for dragging the mini frame around */ 
 322     g_signal_connect (m_mainWidget
, "button_press_event", 
 323                       G_CALLBACK (gtk_window_button_press_callback
), this); 
 324     g_signal_connect (m_mainWidget
, "button_release_event", 
 325                       G_CALLBACK (gtk_window_button_release_callback
), this); 
 326     g_signal_connect (m_mainWidget
, "motion_notify_event", 
 327                       G_CALLBACK (gtk_window_motion_notify_callback
), this); 
 332 void wxMiniFrame::SetTitle( const wxString 
&title 
) 
 334     wxFrame::SetTitle( title 
); 
 336     gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true ); 
 339 #endif // wxUSE_MINIFRAME