core: account for work areas that don't start at 0,0 in resize_preview
[luccawm.git] / core / lucca-graphicaltile.c
blobdee6fce6981ea881071ea1a2a5b317aea73a0b9b
1 /* Copyright (c) 2008 Vincent Povirk
3 Permission is hereby granted, free of charge, to any person
4 obtaining a copy of this software and associated documentation
5 files (the "Software"), to deal in the Software without
6 restriction, including without limitation the rights to use,
7 copy, modify, merge, publish, distribute, sublicense, and/or sell
8 copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following
10 conditions:
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 OTHER DEALINGS IN THE SOFTWARE.
25 #include "lucca-core-private.h"
27 /* Implementation of LuccaGraphicalTile */
29 static GObjectClass* parent_class = NULL;
31 /* struct used to store a managed LuccaWindow and its titlebar widgets */
32 typedef struct {
33 LuccaWindow* window;
34 LuccaGraphicalTile* tile;
36 GtkWidget* eventbox;
37 GtkWidget* hbox;
38 GtkWidget* title_label;
39 GtkWidget* splitd_button;
40 GtkWidget* splitr_button;
41 GtkWidget* close_button;
43 gulong gain_focus_handler_id;
44 gulong lose_focus_handler_id;
45 gulong mouse_in_handler_id;
46 gulong titlechange_handler_id;
47 } WindowInfo;
49 /* event listener declarations */
50 static void on_clientarea_resize(GtkWidget* widget, GtkAllocation* allocation, gpointer user_data);
52 static gboolean on_titlebar_buttondown(GtkWidget* widget, GdkEventButton* event, gpointer user_data);
54 static gboolean on_titlebar_buttonup(GtkWidget* widget, GdkEventButton* event, gpointer user_data);
56 static void on_splitd_click(GtkButton* button, gpointer user_data);
58 static void on_splitr_click(GtkButton* button, gpointer user_data);
60 static void on_close_click(GtkButton* button, gpointer user_data);
62 static void on_tile_configure(LuccaLayoutTile* tile, gpointer user_data);
64 static void on_tile_delete(LuccaLayoutTile* tile, gpointer user_data);
66 static void on_lost_ownership(LuccaWindow* window, gpointer user_data);
68 static void on_gain_focus(LuccaWindow* window, gpointer user_data);
70 static void on_lose_focus(LuccaWindow* window, gpointer user_data);
72 static void on_mouse_in(LuccaWindow* window, gpointer user_data);
74 static void on_titlechange(LuccaWindow* window, GParamSpec* arg1, gpointer user_data);
76 static gboolean on_previewparent_expose(GtkWidget* widget, gpointer user_data);
78 /* property id's */
79 enum {
80 PROP_WORKAREA=1,
81 PROP_TILE,
82 PROP_APPLICATION
85 static void lucca_graphicaltile_init(GTypeInstance* instance, gpointer g_class) {
86 LuccaGraphicalTile* tile = LUCCA_GRAPHICALTILE(instance);
88 tile->dispose_has_run = FALSE;
90 tile->workarea = NULL;
91 tile->tile = NULL;
92 tile->window = NULL;
94 tile->is_previewing = FALSE;
95 tile->preview_parent = NULL;
97 tile->deleting = FALSE;
99 tile->visible_window = NULL;
100 tile->window_infos = NULL;
101 tile->window_infos_recent = NULL;
104 static void lucca_graphicaltile_dispose(GObject* obj) {
105 LuccaGraphicalTile* tile = LUCCA_GRAPHICALTILE(obj);
106 GSList* item;
108 if (tile->dispose_has_run) {
109 return;
111 tile->dispose_has_run = TRUE;
113 if (tile->tile)
114 g_object_unref(tile->tile);
116 if (tile->window)
117 g_object_unref(tile->window);
119 if (tile->preview_parent)
120 g_object_unref(tile->preview_parent);
122 for (item=tile->window_infos; item!=NULL; item=item->next) {
123 WindowInfo* info = (WindowInfo*)item->data;
125 g_signal_handler_disconnect(info->window, info->gain_focus_handler_id);
126 g_signal_handler_disconnect(info->window, info->lose_focus_handler_id);
127 g_signal_handler_disconnect(info->window, info->mouse_in_handler_id);
128 g_signal_handler_disconnect(info->window, info->titlechange_handler_id);
130 g_object_unref(info->window);
132 g_slice_free(WindowInfo, item->data);
134 g_slist_free(tile->window_infos);
135 g_slist_free(tile->window_infos_recent);
137 G_OBJECT_CLASS(parent_class)->dispose(obj);
140 /* lucca_graphicaltile_refresh_position: sets a LuccaGraphicalTile's size and position to match its LuccaLayoutTile */
141 static void lucca_graphicaltile_refresh_position(LuccaGraphicalTile* tile) {
142 gint x, y, width, height;
143 GtkRequisition requisition;
145 if (tile->is_previewing)
146 return;
148 g_object_get(tile->tile,
149 "x", &x,
150 "y", &y,
151 "width", &width,
152 "height", &height,
153 NULL);
155 gtk_widget_size_request(tile->toplevel_vbox, &requisition);
157 lucca_window_configure(tile->window, GTK_WIDGET(tile->workarea->eventbox)->window, x, y, width, height, TRUE);
160 /* lucca_graphicaltile_construct: called after all construction properties have been set */
161 static void lucca_graphicaltile_construct(LuccaGraphicalTile* tile) {
162 GtkWindow* tile_gtkwindow;
164 tile->window = g_object_ref(lucca_display_create_internal(tile->workarea->display));
166 g_object_get(tile->window, "window", &tile_gtkwindow, NULL);
168 tile->toplevel_vbox = gtk_vbox_new(FALSE, 0);
169 tile->titlebar_hbox = gtk_hbox_new(TRUE, 0);
170 tile->titlebar_separator = gtk_hseparator_new();
171 tile->clientspace_widget = gtk_label_new("(no window)");
173 gtk_container_add(GTK_CONTAINER(tile_gtkwindow), tile->toplevel_vbox);
175 gtk_box_pack_start(GTK_BOX(tile->toplevel_vbox),
176 tile->titlebar_hbox,
177 FALSE, /* expand */
178 FALSE, /* fill */
179 0 /* padding */
182 gtk_box_pack_start(GTK_BOX(tile->toplevel_vbox),
183 tile->titlebar_separator,
184 FALSE, /* expand */
185 FALSE, /* fill */
186 0 /* padding */
189 gtk_box_pack_end(GTK_BOX(tile->toplevel_vbox),
190 tile->clientspace_widget,
191 TRUE, /* expand */
192 TRUE, /* fill */
193 0 /* padding */
196 gtk_widget_show(tile->toplevel_vbox);
197 gtk_widget_show(tile->titlebar_hbox);
198 gtk_widget_show(tile->titlebar_separator);
199 gtk_widget_show(tile->clientspace_widget);
201 lucca_graphicaltile_refresh_position(tile);
203 g_signal_connect_after(tile->clientspace_widget, "size-allocate", G_CALLBACK(on_clientarea_resize), tile);
205 g_signal_connect(tile->tile, "configure", G_CALLBACK(on_tile_configure), tile);
206 g_signal_connect(tile->tile, "delete", G_CALLBACK(on_tile_delete), tile);
208 g_object_unref(tile_gtkwindow);
211 static void lucca_graphicaltile_set_property(GObject* object, guint property_id, const GValue* value, GParamSpec* pspec) {
212 LuccaGraphicalTile* tile = LUCCA_GRAPHICALTILE(object);
214 switch (property_id) {
215 case PROP_WORKAREA:
216 tile->workarea = g_object_ref(g_value_get_object(value));
217 if (tile->tile != NULL)
218 lucca_graphicaltile_construct(tile);
219 break;
220 case PROP_TILE:
221 tile->tile = g_object_ref(g_value_get_object(value));
222 if (tile->workarea != NULL)
223 lucca_graphicaltile_construct(tile);
224 break;
225 default:
226 G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec);
227 break;
231 static void lucca_graphicaltile_get_property(GObject* object, guint property_id, GValue* value, GParamSpec* pspec) {
232 LuccaGraphicalTile* tile = LUCCA_GRAPHICALTILE(object);
234 switch (property_id) {
235 case PROP_WORKAREA:
236 g_value_set_object(value, tile->workarea);
237 break;
238 default:
239 G_OBJECT_WARN_INVALID_PROPERTY_ID(object,property_id,pspec);
240 break;
244 static void lucca_graphicaltile_class_init(gpointer g_class, gpointer class_data) {
245 LuccaGraphicalTileClass* klass = (LuccaGraphicalTileClass*)g_class;
246 GObjectClass* gobclass = G_OBJECT_CLASS(g_class);
247 GParamSpec *pspec;
249 /* method overrides */
250 gobclass->dispose = lucca_graphicaltile_dispose;
251 gobclass->set_property = lucca_graphicaltile_set_property;
252 gobclass->get_property = lucca_graphicaltile_get_property;
254 /* properties */
255 pspec = g_param_spec_object(
256 "workarea",
257 "workarea",
258 "The LuccaWorkArea that created this object",
259 LUCCA_TYPE_WORKAREA,
260 G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY);
261 g_object_class_install_property(gobclass, PROP_WORKAREA, pspec);
263 pspec = g_param_spec_object(
264 "tile",
265 "layout tile",
266 "The LuccaLayoutTile that controls this object's size and position",
267 LUCCA_TYPE_LAYOUTTILE,
268 G_PARAM_READABLE|G_PARAM_WRITABLE|G_PARAM_CONSTRUCT_ONLY);
269 g_object_class_install_property(gobclass, PROP_TILE, pspec);
271 parent_class = g_type_class_peek_parent(klass);
274 GType lucca_graphicaltile_get_type() {
275 static GType type = 0;
276 if (type == 0) {
277 static const GTypeInfo info = {
278 sizeof (LuccaGraphicalTileClass),
279 NULL, /* base_init */
280 NULL, /* base_finalize */
281 lucca_graphicaltile_class_init,
282 NULL, /* class_finalize */
283 NULL, /* class_data */
284 sizeof (LuccaGraphicalTile),
285 0, /* n_preallocs */
286 lucca_graphicaltile_init
288 type = g_type_register_static (G_TYPE_OBJECT, "LuccaGraphicalTileType", &info, 0);
290 return type;
293 /* Event listeners */
295 /* called when the label representing client area is resized */
296 static void on_clientarea_resize(GtkWidget* widget, GtkAllocation* allocation, gpointer user_data) {
297 LuccaGraphicalTile* tile = LUCCA_GRAPHICALTILE(user_data);
298 GtkWindow* tile_gtkwindow;
300 g_object_get(tile->window, "window", &tile_gtkwindow, NULL);
302 if (tile->visible_window != NULL) {
303 lucca_window_configure(tile->visible_window,
304 GTK_WIDGET(tile_gtkwindow)->window,
305 allocation->x, allocation->y,
306 allocation->width, allocation->height,
307 TRUE);
310 g_object_unref(tile_gtkwindow);
313 /* called when a mouse button is pressed on the titlebar */
314 static gboolean on_titlebar_buttondown(GtkWidget* widget, GdkEventButton* event, gpointer user_data) {
315 WindowInfo* info = (WindowInfo*)user_data;
317 lucca_graphicaltile_set_visible_window(info->tile, info->window);
319 lucca_window_give_focus(info->window);
321 return FALSE;
324 /* called when a mouse button is released on the titlebar */
325 static gboolean on_titlebar_buttonup(GtkWidget* widget, GdkEventButton* event, gpointer user_data) {
326 WindowInfo* info = (WindowInfo*)user_data;
327 gint event_x_root, event_y_root;
328 gint workarea_x_root, workarea_y_root;
329 LuccaGraphicalTile* drop_target;
331 event_x_root = (gint)event->x_root;
332 event_y_root = (gint)event->y_root;
334 gdk_window_get_root_origin(GTK_WIDGET(info->tile->workarea->eventbox)->window, &workarea_x_root, &workarea_y_root);
336 drop_target = lucca_workarea_get_tile_at_position(info->tile->workarea, event_x_root-workarea_x_root, event_y_root-workarea_y_root);
338 if (drop_target != NULL && drop_target != info->tile) {
339 LuccaWindow* window = info->window;
341 lucca_graphicaltile_add_window(drop_target, window);
342 lucca_graphicaltile_set_visible_window(drop_target, window);
345 return FALSE;
348 /* called when the "split down" button is clicked */
349 static void on_splitd_click(GtkButton* button, gpointer user_data) {
350 WindowInfo* info = (WindowInfo*)user_data;
351 LuccaLayoutTile* newlayouttile;
352 LuccaGraphicalTile* newgraphicaltile;
353 GdkGeometry tile_geometry;
354 GdkWindowHints tile_geom_mask=0;
356 tile_geometry.min_width = 70;
357 tile_geometry.min_height = 70;
358 tile_geom_mask |= GDK_HINT_MIN_SIZE;
360 newlayouttile = lucca_layouttile_split(info->tile->tile, LUCCA_SIDE_BOTTOM, tile_geometry, tile_geom_mask);
362 if (newlayouttile != NULL) {
363 newgraphicaltile = lucca_workarea_get_graphicaltile(info->tile->workarea, newlayouttile);
365 lucca_graphicaltile_add_window(newgraphicaltile, info->window);
369 /* called when the "split right" button is clicked */
370 static void on_splitr_click(GtkButton* button, gpointer user_data) {
371 WindowInfo* info = (WindowInfo*)user_data;
372 LuccaLayoutTile* newlayouttile;
373 LuccaGraphicalTile* newgraphicaltile;
374 GdkGeometry tile_geometry;
375 GdkWindowHints tile_geom_mask=0;
377 tile_geometry.min_width = 70;
378 tile_geometry.min_height = 70;
379 tile_geom_mask |= GDK_HINT_MIN_SIZE;
381 newlayouttile = lucca_layouttile_split(info->tile->tile, LUCCA_SIDE_RIGHT, tile_geometry, tile_geom_mask);
383 if (newlayouttile != NULL) {
384 newgraphicaltile = lucca_workarea_get_graphicaltile(info->tile->workarea, newlayouttile);
386 lucca_graphicaltile_add_window(newgraphicaltile, info->window);
390 /* called when the close button is clicked */
391 static void on_close_click(GtkButton* button, gpointer user_data) {
392 WindowInfo* info = (WindowInfo*)user_data;
394 lucca_window_close(info->window);
397 /* called when our LayoutTile is resized */
398 static void on_tile_configure(LuccaLayoutTile* tile, gpointer user_data) {
399 LuccaGraphicalTile* graphicaltile = LUCCA_GRAPHICALTILE(user_data);
401 lucca_graphicaltile_cancel_preview(graphicaltile);
403 lucca_graphicaltile_refresh_position(graphicaltile);
406 /* called when our LayoutTile is deleted */
407 static void on_tile_delete(LuccaLayoutTile* tile, gpointer user_data) {
408 LuccaGraphicalTile* graphicaltile = LUCCA_GRAPHICALTILE(user_data);
409 LuccaGraphicalTile* refuge_tile;
410 guint x, y;
411 GSList* item;
413 graphicaltile->deleting = TRUE; /* this makes us not bother trying to delete windows from this tile as they're being moved to another tile; our window is about to go away anyway and we should be collected soon so it doesn't matter */
415 /* figure out where our windows should go; if we were deleted, it's because another tile is now using the space, so we look for the tile there */
416 g_object_get(tile, "x", &x, "y", &y, NULL);
417 refuge_tile = lucca_workarea_get_tile_at_position(graphicaltile->workarea, x, y);
419 /* now move our windows to someplace safe; we can iterate the list safely because deleting==TRUE means items won't be deleted as we go */
420 for (item=graphicaltile->window_infos; item!=NULL; item=item->next){
421 WindowInfo* info = (WindowInfo*)item->data;
423 lucca_graphicaltile_add_window(refuge_tile, info->window);
426 /* hide this tile's window */
427 lucca_window_withdraw(graphicaltile->window);
429 /* remove this tile's entry from the workarea's list */
430 graphicaltile->workarea->tiles = g_slist_remove(graphicaltile->workarea->tiles, graphicaltile);
431 g_object_unref(graphicaltile);
434 /* called when another object takes over management of a window */
435 static void on_lost_ownership(LuccaWindow* window, gpointer user_data) {
436 WindowInfo* info = (WindowInfo*)user_data;
438 if (info->tile->deleting)
439 return;
441 /* delete the window's titlebar */
442 gtk_container_remove(GTK_CONTAINER(info->tile->titlebar_hbox), info->eventbox);
444 /* remove its info structure from the lists */
445 info->tile->window_infos = g_slist_remove(info->tile->window_infos, info);
446 info->tile->window_infos_recent = g_slist_remove(info->tile->window_infos_recent, info);
448 /* if this was the visible window, choose another one */
449 if (info->window == info->tile->visible_window) {
450 if (info->tile->window_infos_recent != NULL) {
451 lucca_graphicaltile_set_visible_window(info->tile, ((WindowInfo*)info->tile->window_infos_recent->data)->window);
453 else {
454 info->tile->visible_window = NULL;
458 /* free resources associated with owning this window */
459 g_signal_handler_disconnect(info->window, info->gain_focus_handler_id);
460 g_signal_handler_disconnect(info->window, info->lose_focus_handler_id);
461 g_signal_handler_disconnect(info->window, info->mouse_in_handler_id);
462 g_signal_handler_disconnect(info->window, info->titlechange_handler_id);
463 g_object_unref(info->window);
465 g_slice_free(WindowInfo, info);
468 static void on_gain_focus(LuccaWindow* window, gpointer user_data) {
469 WindowInfo* info = (WindowInfo*)user_data;
471 gtk_widget_modify_base(info->eventbox, GTK_STATE_NORMAL, &(info->eventbox->style->bg[GTK_STATE_SELECTED]));
472 gtk_widget_modify_bg(info->eventbox, GTK_STATE_NORMAL, &(info->eventbox->style->bg[GTK_STATE_SELECTED]));
474 gtk_widget_modify_base(info->hbox, GTK_STATE_NORMAL, &(info->hbox->style->bg[GTK_STATE_SELECTED]));
475 gtk_widget_modify_bg(info->hbox, GTK_STATE_NORMAL, &(info->hbox->style->bg[GTK_STATE_SELECTED]));
477 gtk_widget_modify_bg(info->title_label, GTK_STATE_NORMAL, &(info->title_label->style->bg[GTK_STATE_SELECTED]));
478 gtk_widget_modify_fg(info->title_label, GTK_STATE_NORMAL, &(info->title_label->style->fg[GTK_STATE_SELECTED]));
480 /* mark this window as the most recently-focused window */
481 info->tile->window_infos_recent = g_slist_prepend(g_slist_remove(info->tile->window_infos_recent, info), info);
484 static void on_lose_focus(LuccaWindow* window, gpointer user_data) {
485 WindowInfo* info = (WindowInfo*)user_data;
487 gtk_widget_modify_base(info->eventbox, GTK_STATE_NORMAL, NULL);
488 gtk_widget_modify_bg(info->eventbox, GTK_STATE_NORMAL, NULL);
490 gtk_widget_modify_base(info->hbox, GTK_STATE_NORMAL, NULL);
491 gtk_widget_modify_bg(info->hbox, GTK_STATE_NORMAL, NULL);
493 gtk_widget_modify_bg(info->title_label, GTK_STATE_NORMAL, NULL);
494 gtk_widget_modify_fg(info->title_label, GTK_STATE_NORMAL, NULL);
497 static void on_mouse_in(LuccaWindow* window, gpointer user_data) {
498 /* WindowInfo* info = (WindowInfo*)user_data; */
500 lucca_window_give_focus(window);
503 static void on_titlechange(LuccaWindow* window, GParamSpec* arg1, gpointer user_data) {
504 WindowInfo* info = (WindowInfo*)user_data;
505 gchar* title;
507 g_object_get(window, "requested-title", &title, NULL);
509 gtk_label_set_text(GTK_LABEL(info->title_label), title);
511 g_free(title);
514 static gboolean on_previewparent_expose(GtkWidget* widget, gpointer user_data) {
515 /* LuccaGraphicalTile* tile = LUCCA_GRAPHICALTILE(user_data); */
517 gdk_draw_rectangle(widget->window, widget->style->fg_gc[GTK_STATE_SELECTED], TRUE, 0, 0, widget->allocation.width, widget->allocation.height);
519 return TRUE;
522 /* Method definitions */
524 LuccaWindow* lucca_graphicaltile_get_visible_window(LuccaGraphicalTile* tile) {
525 return tile->visible_window;
528 void lucca_graphicaltile_set_visible_window(LuccaGraphicalTile* tile, LuccaWindow* window) {
529 GtkWindow* tile_gtkwindow;
530 GtkAllocation allocation;
531 gboolean focused;
533 if (tile->visible_window == window)
534 return;
536 g_object_get(window, "focused", &focused, NULL);
538 g_object_get(tile->window, "window", &tile_gtkwindow, NULL);
540 allocation = tile->clientspace_widget->allocation;
542 if (tile->visible_window != NULL) {
543 lucca_window_configure(tile->visible_window, GTK_WIDGET(tile_gtkwindow)->window, allocation.x, allocation.y, allocation.width, allocation.height, FALSE);
546 tile->visible_window = window;
548 if (focused)
549 lucca_window_give_focus(window);
551 lucca_window_configure(tile->visible_window, GTK_WIDGET(tile_gtkwindow)->window, allocation.x, allocation.y, allocation.width, allocation.height, TRUE);
553 g_object_unref(tile_gtkwindow);
556 void lucca_graphicaltile_add_window(LuccaGraphicalTile* tile, LuccaWindow* window) {
557 WindowInfo* info;
558 gchar* title;
559 GClosure* ownership_callback;
561 info = g_slice_new(WindowInfo);
563 g_object_get(window, "requested-title", &title, NULL);
565 info->window = g_object_ref(window);
566 info->tile = tile;
568 /* create a titlebar for this window */
569 info->eventbox = gtk_event_box_new();
570 info->hbox = gtk_hbox_new(FALSE, 0);
571 info->title_label = gtk_label_new(title);
572 info->splitd_button = gtk_button_new_with_label("d");
573 info->splitr_button = gtk_button_new_with_label("r");
574 info->close_button = gtk_button_new_with_label("x");
576 gtk_button_set_relief(GTK_BUTTON(info->splitd_button), GTK_RELIEF_HALF);
577 gtk_button_set_relief(GTK_BUTTON(info->splitr_button), GTK_RELIEF_HALF);
578 gtk_button_set_relief(GTK_BUTTON(info->close_button), GTK_RELIEF_HALF);
580 gtk_container_add(GTK_CONTAINER(info->eventbox), info->hbox);
582 gtk_box_pack_start(GTK_BOX(info->hbox),
583 info->title_label,
584 TRUE, /* expand */
585 TRUE, /* fill */
586 0 /* padding */
587 ); gint x, y, width, height;
589 g_object_get(tile->tile,
590 "x", &x,
591 "y", &y,
592 "width", &width,
593 "height", &height,
594 NULL);
596 gtk_box_pack_end(GTK_BOX(info->hbox),
597 info->close_button,
598 FALSE, /* expand */
599 FALSE, /* fill */
600 0 /* padding */
603 gtk_box_pack_end(GTK_BOX(info->hbox),
604 info->splitr_button,
605 FALSE, /* expand */
606 FALSE, /* fill */
607 2 /* padding */
610 gtk_box_pack_end(GTK_BOX(info->hbox),
611 info->splitd_button,
612 FALSE, /* expand */
613 FALSE, /* fill */
614 0 /* padding */
617 gtk_widget_show_all(info->eventbox);
619 g_signal_connect(info->eventbox, "button-press-event", G_CALLBACK(on_titlebar_buttondown), info);
620 g_signal_connect(info->eventbox, "button-release-event", G_CALLBACK(on_titlebar_buttonup), info);
621 g_signal_connect(info->splitd_button, "clicked", G_CALLBACK(on_splitd_click), info);
622 g_signal_connect(info->splitr_button, "clicked", G_CALLBACK(on_splitr_click), info);
623 g_signal_connect(info->close_button, "clicked", G_CALLBACK(on_close_click), info);
624 info->gain_focus_handler_id = g_signal_connect(window, "gain-focus", G_CALLBACK(on_gain_focus), info);
625 info->lose_focus_handler_id = g_signal_connect(window, "lose-focus", G_CALLBACK(on_lose_focus), info);
626 info->mouse_in_handler_id = g_signal_connect(window, "mouse-in", G_CALLBACK(on_mouse_in), info);
627 info->titlechange_handler_id = g_signal_connect(window, "notify::requested-title", G_CALLBACK(on_titlechange), info);
629 /* add the titlebar to the titlebar area of this tile */
630 gtk_box_pack_start(GTK_BOX(tile->titlebar_hbox),
631 info->eventbox,
632 TRUE, /* expand */
633 TRUE, /* fill */
634 0 /* padding */
637 /* add the window to our list */
638 tile->window_infos = g_slist_append(tile->window_infos, info);
639 tile->window_infos_recent = g_slist_append(tile->window_infos_recent, info);
641 /* take over "ownership" of this window */
642 ownership_callback = g_cclosure_new(G_CALLBACK(on_lost_ownership), info, NULL);
643 g_closure_set_marshal(ownership_callback, g_cclosure_marshal_VOID__VOID);
644 lucca_window_change_owner(window, ownership_callback);
646 /* recalculate the titlebar size and client space, ensuring that the window won't be initially mapped with a wrong size */
647 lucca_graphicaltile_refresh_position(tile);
649 /* make this window visible if the tile was empty */
650 if (tile->visible_window == NULL)
651 lucca_graphicaltile_set_visible_window(tile, window);
652 else {
653 /* if we don't make this window visible, hide it */
654 GtkWindow* tile_gtkwindow;
656 g_object_get(tile->window, "window", &tile_gtkwindow, NULL);
658 if (tile->visible_window != NULL) {
659 lucca_window_configure(window,
660 GTK_WIDGET(tile_gtkwindow)->window,
661 tile->clientspace_widget->allocation.x, tile->clientspace_widget->allocation.y,
662 tile->clientspace_widget->allocation.width, tile->clientspace_widget->allocation.height,
663 FALSE);
666 g_object_unref(tile_gtkwindow);
669 g_free(title);
672 void lucca_graphicaltile_resize_preview(LuccaGraphicalTile* tile, gint x, gint y, gint width, gint height) {
673 guint bordersize;
674 GtkWindow* preview_gtkparent;
675 gint workarea_x, workarea_y;
677 if (!tile->is_previewing) {
678 tile->preview_parent = lucca_display_create_internal(tile->workarea->display);
679 tile->is_previewing = TRUE;
682 g_object_get(tile->workarea->layout, "border-size", &bordersize, NULL);
684 g_object_get(tile->preview_parent, "window", &preview_gtkparent, NULL);
686 g_object_get(tile->workarea->screen, "workarea-x", &workarea_x, "workarea_y", &workarea_y, NULL);
688 g_signal_connect(preview_gtkparent, "expose-event", G_CALLBACK(on_previewparent_expose), tile);
690 lucca_window_configure(tile->preview_parent, lucca_screen_get_root(tile->workarea->screen), x+workarea_x-bordersize, y+workarea_y-bordersize, width+bordersize*2, height+bordersize*2, TRUE);
692 lucca_window_configure(tile->window, GTK_WIDGET(preview_gtkparent)->window, bordersize, bordersize, width, height, TRUE);
695 void lucca_graphicaltile_cancel_preview(LuccaGraphicalTile* tile) {
696 if (tile->is_previewing) {
697 tile->is_previewing = FALSE;
699 lucca_graphicaltile_refresh_position(tile);
701 lucca_window_withdraw(tile->preview_parent);
703 g_object_unref(tile->preview_parent);
704 tile->preview_parent = NULL;
708 GList* lucca_graphicaltile_get_windows(LuccaGraphicalTile* tile) {
709 GList* result=NULL;
710 GSList* item;
712 for (item=tile->window_infos; item!=NULL; item=item->next) {
713 WindowInfo* windowinfo = (WindowInfo*)item->data;
715 result = g_list_prepend(result, windowinfo->window);
718 return result;