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/settings.h"
19 #include "wx/dcclient.h"
23 #include "wx/gtk/win_gtk.h"
24 #include "wx/gtk/private.h"
26 //-----------------------------------------------------------------------------
28 //-----------------------------------------------------------------------------
30 extern bool g_blockEventsOnDrag
;
31 extern bool g_blockEventsOnScroll
;
32 extern GtkWidget
*wxGetRootWindow();
34 //-----------------------------------------------------------------------------
35 // "expose_event" of m_mainWidget
36 //-----------------------------------------------------------------------------
38 // StepColour() it a utility function that simply darkens
39 // or lightens a color, based on the specified percentage
40 static wxColor
StepColour(const wxColor
& c
, int percent
)
42 int r
= c
.Red(), g
= c
.Green(), b
= c
.Blue();
43 return wxColour((unsigned char)wxMin((r
*percent
)/100,255),
44 (unsigned char)wxMin((g
*percent
)/100,255),
45 (unsigned char)wxMin((b
*percent
)/100,255));
48 static wxColor
LightContrastColour(const wxColour
& c
)
52 // if the color is especially dark, then
53 // make the contrast even lighter
54 if (c
.Red() < 128 && c
.Green() < 128 && c
.Blue() < 128)
57 return StepColour(c
, amount
);
61 static gboolean
gtk_window_own_expose_callback(GtkWidget
* widget
, GdkEventExpose
* gdk_event
, wxMiniFrame
* win
)
63 if (!win
->m_hasVMT
|| gdk_event
->count
> 0)
66 GtkPizza
*pizza
= GTK_PIZZA(widget
);
68 gtk_paint_shadow (widget
->style
,
72 NULL
, NULL
, NULL
, // FIXME: No clipping?
74 win
->m_width
, win
->m_height
);
76 int style
= win
->GetWindowStyle();
81 wxImplDC
*impl
= dc
.GetImpl();
82 wxGTKClientImplDC
*client_impl
= wxDynamicCast( impl
, wxGTKClientImplDC
);
84 client_impl
->m_window
= pizza
->bin_window
;
87 dc
.m_window
= pizza
->bin_window
;
90 if (style
& wxRESIZE_BORDER
)
92 dc
.SetBrush( *wxGREY_BRUSH
);
93 dc
.SetPen( *wxTRANSPARENT_PEN
);
94 dc
.DrawRectangle( win
->m_width
- 14, win
->m_height
-14, 14, 14 );
97 if (!win
->GetTitle().empty() &&
98 ((style
& wxCAPTION
) ||
99 (style
& wxTINY_CAPTION_HORIZ
) ||
100 (style
& wxTINY_CAPTION_VERT
)))
102 dc
.SetFont( *wxSMALL_FONT
);
103 int height
= dc
.GetCharHeight();
105 wxBrush
brush( LightContrastColour( wxSystemSettings::GetColour(wxSYS_COLOUR_HIGHLIGHT
) ) );
106 dc
.SetBrush( brush
);
107 dc
.SetPen( *wxTRANSPARENT_PEN
);
108 dc
.DrawRectangle( 3, 3, win
->m_width
- 7, height
);
110 dc
.SetTextForeground( *wxWHITE
);
111 dc
.DrawText( win
->GetTitle(), 6, 3 );
113 if (style
& wxCLOSE_BOX
)
114 dc
.DrawBitmap( win
->m_closeButton
, win
->m_width
-19, 2, true );
120 //-----------------------------------------------------------------------------
121 // "button_press_event" of m_mainWidget
122 //-----------------------------------------------------------------------------
125 static gint
gtk_window_button_press_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
127 if (!win
->m_hasVMT
) return FALSE
;
128 if (g_blockEventsOnDrag
) return TRUE
;
129 if (g_blockEventsOnScroll
) return TRUE
;
131 if (win
->m_isDragging
) return TRUE
;
133 GtkPizza
*pizza
= GTK_PIZZA(widget
);
134 if (gdk_event
->window
!= pizza
->bin_window
) return TRUE
;
136 int style
= win
->GetWindowStyle();
138 int y
= (int)gdk_event
->y
;
139 int x
= (int)gdk_event
->x
;
141 if ((style
& wxRESIZE_BORDER
) &&
142 (x
> win
->m_width
-14) && (y
> win
->m_height
-14))
144 GtkWidget
*ancestor
= gtk_widget_get_toplevel( widget
);
146 GdkWindow
*source
= GTK_PIZZA(widget
)->bin_window
;
150 gdk_window_get_origin( source
, &org_x
, &org_y
);
152 gtk_window_begin_resize_drag (GTK_WINDOW (ancestor
),
153 GDK_WINDOW_EDGE_SOUTH_EAST
,
162 if ((style
& wxCLOSE_BOX
) &&
163 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
165 if ((y
> 3) && (y
< 19) && (x
> win
->m_width
-19) && (x
< win
->m_width
-3))
173 dc
.SetFont( *wxSMALL_FONT
);
174 int height
= dc
.GetCharHeight() + 1;
177 if (y
> height
) return TRUE
;
179 gdk_window_raise( win
->m_widget
->window
);
181 gdk_pointer_grab( widget
->window
, FALSE
,
183 (GDK_BUTTON_PRESS_MASK
|
184 GDK_BUTTON_RELEASE_MASK
|
185 GDK_POINTER_MOTION_MASK
|
186 GDK_POINTER_MOTION_HINT_MASK
|
187 GDK_BUTTON_MOTION_MASK
|
188 GDK_BUTTON1_MOTION_MASK
),
191 (unsigned int) GDK_CURRENT_TIME
);
198 win
->m_isDragging
= true;
204 //-----------------------------------------------------------------------------
205 // "button_release_event" of m_mainWidget
206 //-----------------------------------------------------------------------------
209 static gint
gtk_window_button_release_callback( GtkWidget
*widget
, GdkEventButton
*gdk_event
, wxMiniFrame
*win
)
211 if (!win
->m_hasVMT
) return FALSE
;
212 if (g_blockEventsOnDrag
) return TRUE
;
213 if (g_blockEventsOnScroll
) return TRUE
;
215 if (!win
->m_isDragging
) return TRUE
;
217 win
->m_isDragging
= false;
219 int x
= (int)gdk_event
->x
;
220 int y
= (int)gdk_event
->y
;
222 gdk_pointer_ungrab ( (guint32
)GDK_CURRENT_TIME
);
225 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
226 x
+= org_x
- win
->m_diffX
;
227 y
+= org_y
- win
->m_diffY
;
230 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
236 //-----------------------------------------------------------------------------
237 // "leave_notify_event" of m_mainWidget
238 //-----------------------------------------------------------------------------
242 gtk_window_leave_callback( GtkWidget
*widget
, GdkEventCrossing
*gdk_event
, wxMiniFrame
*win
)
244 if (!win
->m_hasVMT
) return FALSE
;
245 if (g_blockEventsOnDrag
) return FALSE
;
247 gdk_window_set_cursor( widget
->window
, NULL
);
253 //-----------------------------------------------------------------------------
254 // "motion_notify_event" of m_mainWidget
255 //-----------------------------------------------------------------------------
259 gtk_window_motion_notify_callback( GtkWidget
*widget
, GdkEventMotion
*gdk_event
, wxMiniFrame
*win
)
261 if (!win
->m_hasVMT
) return FALSE
;
262 if (g_blockEventsOnDrag
) return TRUE
;
263 if (g_blockEventsOnScroll
) return TRUE
;
265 if (gdk_event
->is_hint
)
269 GdkModifierType state
;
270 gdk_window_get_pointer(gdk_event
->window
, &x
, &y
, &state
);
273 gdk_event
->state
= state
;
276 int style
= win
->GetWindowStyle();
278 int x
= (int)gdk_event
->x
;
279 int y
= (int)gdk_event
->y
;
281 if (!win
->m_isDragging
)
283 if (style
& wxRESIZE_BORDER
)
285 if ((x
> win
->m_width
-14) && (y
> win
->m_height
-14))
286 gdk_window_set_cursor( widget
->window
, gdk_cursor_new( GDK_BOTTOM_RIGHT_CORNER
) );
288 gdk_window_set_cursor( widget
->window
, NULL
);
293 win
->m_oldX
= x
- win
->m_diffX
;
294 win
->m_oldY
= y
- win
->m_diffY
;
298 gdk_window_get_origin( widget
->window
, &org_x
, &org_y
);
299 x
+= org_x
- win
->m_diffX
;
300 y
+= org_y
- win
->m_diffY
;
303 gtk_window_move( GTK_WINDOW(win
->m_widget
), x
, y
);
310 //-----------------------------------------------------------------------------
312 //-----------------------------------------------------------------------------
314 static unsigned char close_bits
[]={
315 0xff, 0xff, 0xff, 0xff, 0x07, 0xf0, 0xfb, 0xef, 0xdb, 0xed, 0x8b, 0xe8,
316 0x1b, 0xec, 0x3b, 0xee, 0x1b, 0xec, 0x8b, 0xe8, 0xdb, 0xed, 0xfb, 0xef,
317 0x07, 0xf0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
320 IMPLEMENT_DYNAMIC_CLASS(wxMiniFrame
,wxFrame
)
322 bool wxMiniFrame::Create( wxWindow
*parent
, wxWindowID id
, const wxString
&title
,
323 const wxPoint
&pos
, const wxSize
&size
,
324 long style
, const wxString
&name
)
326 if ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
))
329 if (style
& wxRESIZE_BORDER
)
333 m_isDragging
= false;
339 wxFrame::Create( parent
, id
, title
, pos
, size
, style
, name
);
341 if (m_parent
&& (GTK_IS_WINDOW(m_parent
->m_widget
)))
343 gtk_window_set_transient_for( GTK_WINDOW(m_widget
), GTK_WINDOW(m_parent
->m_widget
) );
346 if ((style
& wxCLOSE_BOX
) &&
347 ((style
& wxCAPTION
) || (style
& wxTINY_CAPTION_HORIZ
) || (style
& wxTINY_CAPTION_VERT
)))
349 wxImage img
= wxBitmap((const char*)close_bits
, 16, 16).ConvertToImage();
350 img
.Replace(0,0,0,123,123,123);
351 img
.SetMaskColour(123,123,123);
352 m_closeButton
= wxBitmap( img
);
355 /* these are called when the borders are drawn */
356 g_signal_connect (m_mainWidget
, "expose_event",
357 G_CALLBACK (gtk_window_own_expose_callback
), this );
359 /* these are required for dragging the mini frame around */
360 g_signal_connect (m_mainWidget
, "button_press_event",
361 G_CALLBACK (gtk_window_button_press_callback
), this);
362 g_signal_connect (m_mainWidget
, "button_release_event",
363 G_CALLBACK (gtk_window_button_release_callback
), this);
364 g_signal_connect (m_mainWidget
, "motion_notify_event",
365 G_CALLBACK (gtk_window_motion_notify_callback
), this);
366 g_signal_connect (m_mainWidget
, "leave_notify_event",
367 G_CALLBACK (gtk_window_leave_callback
), this);
371 void wxMiniFrame::SetTitle( const wxString
&title
)
373 wxFrame::SetTitle( title
);
375 if (GTK_PIZZA(m_mainWidget
)->bin_window
)
376 gdk_window_invalidate_rect( GTK_PIZZA(m_mainWidget
)->bin_window
, NULL
, true );
379 #endif // wxUSE_MINIFRAME