comparison gtk/plugins/win32/winprefs/gtkappbar.c @ 14224:ab8a105eff62

[gaim-migrate @ 16905] First step of getting wingaim working again. libgaim and gtk are compiling. The protocols aren't compiling yet. There are a number of things that are compiling, but should be cleaned up. committer: Tailor Script <tailor@pidgin.im>
author Daniel Atallah <daniel.atallah@gmail.com>
date Sun, 20 Aug 2006 16:49:37 +0000
parents
children
comparison
equal deleted inserted replaced
14223:7c560c01b8f9 14224:ab8a105eff62
1 /*
2 * gaim - WinGaim Options Plugin
3 *
4 * File: gtkappbar.c
5 * Date: August 2, 2003
6 * Description: Appbar functionality for Windows GTK+ applications
7 *
8 * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25 /*
26 * TODO:
27 * - Move 'App on top' feature from Trans plugin to here
28 * - Bug: Multiple Show/Hide Desktop calls causes client area to disappear
29 */
30 #include <windows.h>
31 #include <winver.h>
32 #include <stdio.h>
33 #include <gtk/gtk.h>
34 #include <gdk/gdkwin32.h>
35 #include "gtkappbar.h"
36 #include "debug.h"
37
38 #define APPBAR_CALLBACK WM_USER + 1010
39
40 typedef HMONITOR WINAPI gaim_MonitorFromPoint(POINT, DWORD);
41 typedef HMONITOR WINAPI gaim_MonitorFromWindow(HWND, DWORD);
42 typedef BOOL WINAPI gaim_GetMonitorInfo(HMONITOR, LPMONITORINFO);
43
44 /* Retrieve the rectangular display area from the specified monitor
45 * Return TRUE if successful, otherwise FALSE
46 */
47 static gboolean
48 get_rect_from_monitor(HMODULE hmod, HMONITOR monitor, RECT *rect) {
49 gaim_GetMonitorInfo *the_GetMonitorInfo;
50 MONITORINFO info;
51
52 if (!(the_GetMonitorInfo = (gaim_GetMonitorInfo*)
53 GetProcAddress(hmod, "GetMonitorInfoA"))) {
54 return FALSE;
55 }
56
57 info.cbSize = sizeof(info);
58 if (!the_GetMonitorInfo(monitor, &info)) {
59 return FALSE;
60 }
61
62 CopyRect(rect, &(info.rcMonitor));
63
64 return TRUE;
65 }
66
67 /**
68 * This will only work on Win98+ and Win2K+
69 * Return TRUE if successful, otherwise FALSE
70 */
71 static gboolean
72 get_rect_at_point_multimonitor(POINT pt, RECT *rect) {
73 HMODULE hmod;
74 gaim_MonitorFromPoint *the_MonitorFromPoint;
75 HMONITOR monitor;
76
77 if (!(hmod = GetModuleHandle("user32"))) {
78 return FALSE;
79 }
80
81 if (!(the_MonitorFromPoint = (gaim_MonitorFromPoint*)
82 GetProcAddress(hmod, "MonitorFromPoint"))) {
83 return FALSE;
84 }
85
86 monitor =
87 the_MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
88
89 return get_rect_from_monitor(hmod, monitor, rect);
90 }
91
92 /**
93 * This will only work on Win98+ and Win2K+
94 * Return TRUE if successful, otherwise FALSE
95 */
96 static gboolean
97 get_rect_of_window_multimonitor(HWND window, RECT *rect) {
98 HMODULE hmod;
99 gaim_MonitorFromWindow *the_MonitorFromWindow;
100 HMONITOR monitor;
101
102 if (!(hmod = GetModuleHandle("user32"))) {
103 return FALSE;
104 }
105
106 if (!(the_MonitorFromWindow = (gaim_MonitorFromWindow*)
107 GetProcAddress(hmod, "MonitorFromWindow"))) {
108 return FALSE;
109 }
110
111 monitor =
112 the_MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
113
114 return get_rect_from_monitor(hmod, monitor, rect);
115 }
116
117 /*
118 * Fallback if cannot get the RECT from the monitor directly
119 */
120 static void get_default_workarea(RECT *rect) {
121 if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE)) {
122 /* I don't think this will ever happen */
123 rect->left = 0;
124 rect->top = 0;
125 rect->bottom = GetSystemMetrics(SM_CYSCREEN);
126 rect->right = GetSystemMetrics(SM_CXSCREEN);
127 }
128 }
129
130 /* Retrieve the rectangle of the active work area at a point */
131 static RECT get_rect_at_point(POINT pt) {
132 RECT rc;
133 if (!get_rect_at_point_multimonitor(pt, &rc)) {
134 get_default_workarea(&rc);
135 }
136 return rc;
137 }
138
139 /* Retrieve the rectangle of the active work area of a window*/
140 static RECT get_rect_of_window(HWND window) {
141 RECT rc;
142 if (!get_rect_of_window_multimonitor(window, &rc)) {
143 get_default_workarea(&rc);
144 }
145 return rc;
146 }
147
148 static void get_window_normal_rc(HWND hwnd, RECT *rc) {
149 WINDOWPLACEMENT wplc;
150 GetWindowPlacement(hwnd, &wplc);
151 CopyRect(rc, &wplc.rcNormalPosition);
152 }
153 #if 0
154 static void print_rect(RECT *rc) {
155 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "RECT: L:%ld R:%ld T:%ld B:%ld\n",
156 rc->left, rc->right, rc->top, rc->bottom);
157 }
158 #endif
159 /** Set the window style to be the "Tool Window" style - small header, no min/max buttons */
160 static void set_toolbar(HWND hwnd, gboolean val) {
161 LONG style=0;
162
163 style = GetWindowLong(hwnd, GWL_EXSTYLE);
164 if(val && !(style & WS_EX_TOOLWINDOW))
165 style |= WS_EX_TOOLWINDOW;
166 else if(!val && style & WS_EX_TOOLWINDOW)
167 style &= ~WS_EX_TOOLWINDOW;
168 else
169 return;
170 SetWindowLong(hwnd, GWL_EXSTYLE, style);
171 SetWindowPos(hwnd, 0, 0, 0, 0, 0,
172 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
173
174 /* This really should be the following, but SWP_FRAMECHANGED strangely causes initermittent problems "Show Desktop" done more than once.
175 * Not having SWP_FRAMECHANGED *should* cause the Style not to be applied, but i haven't noticed any problems
176 * SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
177 */
178 }
179 /** Register the window as an appbar */
180 static gboolean gtk_appbar_register(GtkAppBar *ab, HWND hwnd) {
181 APPBARDATA abd;
182
183 abd.cbSize = sizeof(APPBARDATA);
184 abd.hWnd = hwnd;
185 abd.uCallbackMessage = APPBAR_CALLBACK;
186
187 ab->registered = SHAppBarMessage(ABM_NEW, &abd);
188
189 return ab->registered;
190 }
191 /** Unregister the window as an appbar */
192 static gboolean gtk_appbar_unregister(GtkAppBar *ab, HWND hwnd) {
193 APPBARDATA abd;
194
195 if(!ab->registered)
196 return TRUE;
197
198 abd.cbSize = sizeof(APPBARDATA);
199 abd.hWnd = hwnd;
200
201 SHAppBarMessage(ABM_REMOVE, &abd); /** This always returns TRUE */
202
203 ab->registered = FALSE;
204
205 ab->docked = FALSE;
206 ab->docking = FALSE;
207
208 return TRUE;
209 }
210
211 static void gtk_appbar_querypos(GtkAppBar *ab, HWND hwnd, RECT rcWorkspace) {
212 APPBARDATA abd;
213 guint iWidth = 0;
214
215 if(!ab->registered)
216 gtk_appbar_register(ab, hwnd);
217
218 abd.hWnd = hwnd;
219 abd.cbSize = sizeof(APPBARDATA);
220 abd.uEdge = ab->side;
221
222 iWidth = ab->docked_rect.right - ab->docked_rect.left;
223
224 abd.rc.top = rcWorkspace.top;
225 abd.rc.bottom = rcWorkspace.bottom;
226 switch (abd.uEdge)
227 {
228 case ABE_LEFT:
229 abd.rc.left = rcWorkspace.left;
230 abd.rc.right = rcWorkspace.left + iWidth;
231 break;
232
233 case ABE_RIGHT:
234 abd.rc.right = rcWorkspace.right;
235 abd.rc.left = rcWorkspace.right - iWidth;
236 break;
237 }
238
239 /* Ask the system for the screen space */
240 SHAppBarMessage(ABM_QUERYPOS, &abd);
241
242 switch (abd.uEdge)
243 {
244 case ABE_LEFT:
245 abd.rc.right = abd.rc.left + iWidth;
246 break;
247
248 case ABE_RIGHT:
249 abd.rc.left = abd.rc.right - iWidth;
250 break;
251 }
252
253 CopyRect(&(ab->docked_rect), &abd.rc);
254 }
255 /* Actually set the size and screen location of the appbar */
256 static void gtk_appbar_setpos(GtkAppBar *ab, HWND hwnd) {
257 APPBARDATA abd;
258
259 if(!ab->registered)
260 gtk_appbar_register(ab, hwnd);
261
262 abd.hWnd = hwnd;
263 abd.cbSize = sizeof(APPBARDATA);
264 CopyRect(&abd.rc, &(ab->docked_rect));
265 abd.uEdge = ab->side;
266
267 SHAppBarMessage(ABM_SETPOS, &abd);
268 }
269 /** Let any callbacks know that we have docked or undocked */
270 static void gtk_appbar_dispatch_dock_cbs(GtkAppBar *ab, gboolean val) {
271 GList *lst = ab->dock_cbs;
272
273 while(lst) {
274 GtkAppBarDockCB dock_cb = lst->data;
275 dock_cb(val);
276 lst = lst->next;
277 }
278 }
279
280 static GdkFilterReturn wnd_moving(GtkAppBar *ab, GdkXEvent *xevent) {
281 MSG *msg = (MSG*)xevent;
282 POINT cp;
283 RECT *rc = (RECT*)msg->lParam;
284 RECT monRect;
285 int side = -1;
286 long dockAreaWidth = 0;
287
288 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_moving\n");
289
290 GetCursorPos(&cp);
291 monRect = get_rect_at_point(cp);
292
293 dockAreaWidth = (monRect.right - monRect.left) / 10;
294 /* Which part of the screen are we in ? */
295 if (cp.x > (monRect.right - dockAreaWidth)) {
296 side = ABE_RIGHT;
297 } else if (cp.x < (monRect.left + dockAreaWidth)) {
298 side = ABE_LEFT;
299 }
300
301 if(!ab->docked) {
302 if( (side == ABE_RIGHT || side == ABE_LEFT) ) {
303 if( !ab->docking ) {
304 ab->side = side;
305 GetWindowRect(msg->hwnd, &(ab->docked_rect));
306 gtk_appbar_querypos(ab, msg->hwnd, monRect);
307
308 /* save pre-docking height */
309 ab->undocked_height = rc->bottom - rc->top;
310 ab->docking = TRUE;
311 }
312 }
313 else
314 ab->docking = FALSE;
315 }
316 else if(side < 0) {
317 gtk_appbar_unregister(ab, msg->hwnd);
318 rc->bottom = rc->top + ab->undocked_height;
319 }
320
321 /* Switch to toolbar/regular caption*/
322 if(ab->docking)
323 set_toolbar(msg->hwnd, TRUE);
324 else if(!ab->docked)
325 set_toolbar(msg->hwnd, FALSE);
326
327 return GDK_FILTER_CONTINUE;
328 }
329
330 static GdkFilterReturn wnd_sizing(GtkAppBar *ab, GdkXEvent *xevent) {
331 MSG *msg = (MSG*)xevent;
332
333 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_sizing\n");
334 if(ab->docked) {
335 RECT *rc = (RECT*)msg->lParam;
336 if(ab->side == ABE_LEFT && msg->wParam == WMSZ_RIGHT) {
337 ab->docked_rect.right = rc->right;
338 gtk_appbar_setpos(ab, msg->hwnd);
339 }
340 else if(ab->side == ABE_RIGHT && msg->wParam == WMSZ_LEFT) {
341 ab->docked_rect.left = rc->left;
342 gtk_appbar_setpos(ab, msg->hwnd);
343 }
344 return GDK_FILTER_REMOVE;
345 }
346 return GDK_FILTER_CONTINUE;
347 }
348 /** Notify the system that the appbar has been activated */
349 static GdkFilterReturn wnd_activate(GtkAppBar *ab, GdkXEvent *xevent) {
350 if (ab->registered) {
351 APPBARDATA abd;
352 MSG *msg = (MSG*)xevent;
353 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_activate\n");
354
355 abd.hWnd = msg->hwnd;
356 abd.cbSize = sizeof(APPBARDATA);
357
358 SHAppBarMessage(ABM_ACTIVATE, &abd);
359 }
360 return GDK_FILTER_CONTINUE;
361 }
362 /** Notify the system that the appbar's position has changed */
363 static GdkFilterReturn wnd_poschanged(GtkAppBar *ab, GdkXEvent *xevent) {
364 if (ab->registered) {
365 APPBARDATA abd;
366 MSG *msg = (MSG*)xevent;
367 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_poschanged\n");
368
369 abd.hWnd = msg->hwnd;
370 abd.cbSize = sizeof(APPBARDATA);
371
372 SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
373 }
374 return GDK_FILTER_CONTINUE;
375 }
376 /** The window is about to change */
377 static GdkFilterReturn wnd_poschanging(GtkAppBar *ab, GdkXEvent *xevent) {
378 MSG *msg = (MSG*)xevent;
379 WINDOWPOS *wpos = (WINDOWPOS*)msg->lParam;
380
381 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_poschanging\n");
382
383 if(ab->docked || ab->docking) {
384 wpos->x = ab->docked_rect.left;
385 wpos->y = ab->docked_rect.top;
386 wpos->cx = ab->docked_rect.right - ab->docked_rect.left;
387 wpos->cy = ab->docked_rect.bottom - ab->docked_rect.top;
388 if(IsIconic(msg->hwnd))
389 set_toolbar(msg->hwnd, FALSE);
390 /*return GDK_FILTER_REMOVE;*/
391 }
392 return GDK_FILTER_CONTINUE;
393 }
394
395 static GdkFilterReturn wnd_exitsizemove(GtkAppBar *ab, GdkXEvent *xevent) {
396 MSG *msg = (MSG*)xevent;
397
398 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_exitsizemove\n");
399 if(ab->docking) {
400 gtk_appbar_setpos(ab, msg->hwnd);
401 ab->docking = FALSE;
402 ab->docked = TRUE;
403 gtk_appbar_dispatch_dock_cbs(ab, TRUE);
404 }
405 else if(!ab->docked) {
406 gtk_appbar_unregister(ab, msg->hwnd);
407 gtk_appbar_dispatch_dock_cbs(ab, FALSE);
408 }
409
410 return GDK_FILTER_CONTINUE;
411 }
412
413 static GdkFilterReturn wnd_showwindow(GtkAppBar *ab, GdkXEvent *xevent) {
414 MSG *msg = (MSG*)xevent;
415
416 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_showwindow\n");
417 if(msg->wParam && ab->docked) {
418 ab->iconized = FALSE;
419 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "shown\n");
420 ab->docked = FALSE;
421 gtk_appbar_dock(ab, ab->side);
422 }
423 else if(!msg->wParam && ab->docked) {
424 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "hidden\n");
425 gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
426 set_toolbar(GDK_WINDOW_HWND(ab->win->window), FALSE);
427 ab->docked = TRUE;
428 ab->iconized = TRUE;
429 }
430 return GDK_FILTER_CONTINUE;
431 }
432 /** The window's size has changed */
433 static GdkFilterReturn wnd_size(GtkAppBar *ab, GdkXEvent *xevent) {
434 MSG *msg = (MSG*)xevent;
435
436 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_size\n");
437
438 if(msg->wParam == SIZE_MINIMIZED) {
439 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "Minimize\n");
440 if(ab->docked) {
441 gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
442 ab->docked = TRUE;
443 }
444 }
445 else if(msg->wParam == SIZE_RESTORED) {
446 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "Restore\n");
447 if (!ab->iconized && ab->docked) {
448 gtk_appbar_dock(ab, ab->side);
449 }
450 }
451 return GDK_FILTER_CONTINUE;
452 }
453
454 static GdkFilterReturn wnd_nchittest(GtkAppBar *ab, GdkXEvent *xevent) {
455 MSG *msg = (MSG*)xevent;
456
457 if(ab->docked) {
458 UINT ret = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
459
460 switch(ret) {
461 case HTBOTTOM:
462 case HTBOTTOMLEFT:
463 case HTBOTTOMRIGHT:
464 case HTTOP:
465 case HTTOPLEFT:
466 case HTTOPRIGHT:
467 return GDK_FILTER_REMOVE;
468 case HTLEFT:
469 if(ab->side == ABE_LEFT)
470 return GDK_FILTER_REMOVE;
471 break;
472 case HTRIGHT:
473 if(ab->side == ABE_RIGHT)
474 return GDK_FILTER_REMOVE;
475 break;
476 }
477 }
478 return GDK_FILTER_CONTINUE;
479 }
480
481 #if 0
482 static GdkFilterReturn wnd_initmenupopup(GtkAppBar *ab, GdkXEvent *xevent) {
483 MSG *msg = (MSG*)xevent;
484
485 if(ab->docked && HIWORD(msg->lParam)) {
486 HMENU sysmenu = GetSystemMenu(msg->hwnd, FALSE);
487 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "wnd_initpopupmenu: docked: %d ismenu: %d\n", ab->docked, IsMenu(sysmenu));
488 if(EnableMenuItem(sysmenu, SC_MAXIMIZE, MF_BYCOMMAND|MF_GRAYED)<0)
489 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "SC_MAXIMIZE Menu item does not exist\n");
490 if(EnableMenuItem(sysmenu, SC_MOVE, MF_BYCOMMAND|MF_GRAYED)<0)
491 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "SC_MOVE Menu item does not exist\n");
492 return GDK_FILTER_CONTINUE;
493 }
494 else
495 GetSystemMenu(msg->hwnd, TRUE);
496 return GDK_FILTER_CONTINUE;
497 }
498 #endif
499
500 static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) {
501 MSG *msg = (MSG*)xevent;
502 RECT orig;
503
504 switch (msg->wParam) {
505 case ABN_STATECHANGE:
506 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_STATECHANGE\n");
507 break;
508
509 case ABN_FULLSCREENAPP:
510 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_FULLSCREENAPP: %d\n", (BOOL)msg->lParam);
511 if (!ab->iconized && ab->docked) {
512 if ((BOOL)msg->lParam) {
513 SetWindowPos(msg->hwnd, HWND_BOTTOM, 0, 0, 0, 0,
514 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
515 } else {
516 SetWindowPos(msg->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
517 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED);
518 }
519 }
520
521 break;
522
523 case ABN_POSCHANGED:
524 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n");
525 CopyRect(&orig, &(ab->docked_rect));
526 gtk_appbar_querypos(ab, msg->hwnd, get_rect_of_window(msg->hwnd));
527 if (EqualRect(&orig, &(ab->docked_rect)) == 0) {
528 MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top,
529 ab->docked_rect.right - ab->docked_rect.left,
530 ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
531 }
532 gtk_appbar_setpos(ab, msg->hwnd);
533 break;
534 #if 0
535 default:
536 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: %d\n", msg->wParam);
537 #endif
538 }
539 return GDK_FILTER_CONTINUE;
540 }
541
542 static GdkFilterReturn gtk_appbar_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) {
543 MSG *msg = (MSG*)xevent;
544
545 /*printf("MSG: %s\n", message_to_string (msg->message));*/
546 switch(msg->message) {
547 case WM_EXITSIZEMOVE:
548 return wnd_exitsizemove(data, xevent);
549 case WM_WINDOWPOSCHANGING:
550 return wnd_poschanging(data, xevent);
551 case WM_WINDOWPOSCHANGED:
552 return wnd_poschanged(data, xevent);
553 case WM_ACTIVATE:
554 return wnd_activate(data, xevent);
555 case WM_SIZING:
556 return wnd_sizing(data, xevent);
557 case WM_MOVING:
558 return wnd_moving(data, xevent);
559 case WM_SHOWWINDOW:
560 return wnd_showwindow(data, xevent);
561 case WM_NCHITTEST:
562 return wnd_nchittest(data, xevent);
563 #if 0
564 case WM_INITMENUPOPUP:
565 return wnd_initmenupopup(data, xevent);
566 #endif
567 case WM_SIZE:
568 return wnd_size(data, xevent);
569 case APPBAR_CALLBACK:
570 return gtk_appbar_callback(data, xevent);
571 #if 0
572 default:
573 gaim_debug_info("gtkappbar", "gtk_appbar_event_filter %d\n", msg->message);
574 #endif
575 }
576 return GDK_FILTER_CONTINUE;
577 }
578
579 void gtk_appbar_dock(GtkAppBar *ab, UINT side) {
580 RECT orig;
581
582 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_dock\n");
583
584 if(!ab || !IsWindow(GDK_WINDOW_HWND(ab->win->window)))
585 return;
586
587 ab->side = side;
588 get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect));
589 CopyRect(&orig, &(ab->docked_rect));
590 gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window),
591 get_rect_of_window(GDK_WINDOW_HWND(ab->win->window)));
592 if(EqualRect(&orig, &(ab->docked_rect)) == 0)
593 MoveWindow(GDK_WINDOW_HWND(ab->win->window),
594 ab->docked_rect.left,
595 ab->docked_rect.top,
596 ab->docked_rect.right - ab->docked_rect.left,
597 ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
598 gtk_appbar_setpos(ab, GDK_WINDOW_HWND(ab->win->window));
599 set_toolbar(GDK_WINDOW_HWND(ab->win->window), TRUE);
600 ab->docked = TRUE;
601 }
602
603 void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb) {
604 if(!ab)
605 return;
606 ab->dock_cbs = g_list_append(ab->dock_cbs, dock_cb);
607 }
608
609 GtkAppBar *gtk_appbar_add(GtkWidget *win) {
610 GtkAppBar *ab;
611
612 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_add\n");
613
614 if(!win)
615 return NULL;
616 ab = g_new0(GtkAppBar, 1);
617 ab->win = win;
618
619 /* init docking coords */
620 get_window_normal_rc(GDK_WINDOW_HWND(win->window), &(ab->docked_rect));
621
622 /* Add main window filter */
623 gdk_window_add_filter(win->window,
624 gtk_appbar_event_filter,
625 ab);
626 return ab;
627 }
628
629 void gtk_appbar_remove(GtkAppBar *ab) {
630 gaim_debug(GAIM_DEBUG_INFO, "gtkappbar", "gtk_appbar_remove\n");
631
632 if(!ab)
633 return;
634 gdk_window_remove_filter(ab->win->window,
635 gtk_appbar_event_filter,
636 ab);
637 if(ab->docked) {
638 gtk_window_resize(GTK_WINDOW(ab->win),
639 ab->docked_rect.right - ab->docked_rect.left,
640 ab->undocked_height);
641 set_toolbar(GDK_WINDOW_HWND(ab->win->window), FALSE);
642 }
643 gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
644
645 g_free(ab);
646 }