Convert over to use GetOpt::Long and introduce -f and -h.
[fvwm.git] / modules / FvwmIconMan / fvwm.c
blob14f0b80a3fde90ca882a38bdffea0f22f4daf0a7
1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 #include "config.h"
19 #include "FvwmIconMan.h"
20 #include "x.h"
21 #include "xmanager.h"
23 #include "libs/fvwmlib.h"
24 #include "libs/FScreen.h"
25 #include "libs/Module.h"
26 #include "libs/Parse.h"
27 #include "libs/Strings.h"
29 static WinData *fvwm_focus_win = NULL;
31 typedef struct {
32 Ulong paging_enabled;
33 } m_toggle_paging_data;
35 typedef struct {
36 Ulong desknum;
37 } m_new_desk_data;
39 typedef struct {
40 Ulong x, y, desknum;
41 } m_new_page_data;
43 typedef struct {
44 Ulong app_id, frame_id, dbase_entry;
45 } m_minimal_data;
47 typedef struct {
48 Ulong app_id, frame_id, dbase_entry;
49 Ulong xpos, ypos, icon_width, icon_height;
50 } m_icon_data;
52 typedef struct {
53 Ulong app_id, frame_id, dbase_entry;
54 union {
55 Ulong name_long[1];
56 Uchar name[4];
57 } name;
58 } m_name_data;
60 typedef struct {
61 Ulong arg, toggle, id;
62 Uchar str[4];
63 } m_property_data;
65 typedef struct {
66 Ulong app_id, frame_id, dbase_entry;
67 Ulong width, height, depth, picture, mask, alpha;
68 union {
69 Ulong name_long[1];
70 Uchar name[4];
71 } name;
72 } m_mini_icon_data;
74 typedef union {
75 m_toggle_paging_data toggle_paging_data;
76 m_new_desk_data new_desk_data;
77 ConfigWinPacket add_config_data;
78 m_new_page_data new_page_data;
79 m_minimal_data minimal_data;
80 m_icon_data icon_data;
81 m_name_data name_data;
82 m_mini_icon_data mini_icon_data;
83 m_property_data property_data;
84 } FvwmPacketBody;
86 /* only used by count_nonsticky_in_hashtab */
87 static WinManager *the_manager;
89 static int count_nonsticky_in_hashtab(void *arg)
91 WinData *win = (WinData *)arg;
92 WinManager *man = the_manager;
94 if (!(IS_STICKY_ACROSS_DESKS(win) || IS_STICKY_ACROSS_PAGES(win)) &&
95 win->complete && win->manager == man)
97 return 1;
99 return 0;
102 static void set_draw_mode(WinManager *man, int flag)
104 int num;
106 if (!man)
108 return;
111 if (man->we_are_drawing == 0 && flag)
113 draw_manager(man);
115 else if (man->we_are_drawing && !flag)
117 the_manager = man;
118 num = accumulate_walk_hashtab(count_nonsticky_in_hashtab);
119 ConsoleDebug(
120 FVWM, "SetDrawMode on 0x%lx, num = %d\n",
121 (unsigned long)man, num);
123 if (num == 0)
125 return;
127 man->configures_expected = num;
129 man->we_are_drawing = flag;
132 static int drawing(WinManager *man)
134 if (!man)
136 return 1;
139 return man->we_are_drawing;
142 static void got_configure(WinManager *man)
144 if (man && !man->we_are_drawing)
146 man->configures_expected--;
147 ConsoleDebug(
148 FVWM, "got_configure on 0x%lx, num_expected now = %d\n",
149 (unsigned long) man, man->configures_expected);
150 if (man->configures_expected <= 0)
152 set_draw_mode(man, 1);
157 /* MMH <mikehan@best.com> 6/99
158 * Following a gruesome hack this function has been hijacked.
159 * The function is no longer about whether or not the window is in the
160 * viewport, but whether or not the manager wants to display the window,
161 * based on its current location.
163 int win_in_viewport(WinData *win)
165 return check_resolution(win->manager, win);
169 WinData *id_to_win(Ulong id)
171 WinData *win;
173 win = find_win_hashtab(id);
174 if (win == NULL)
176 win = new_windata();
177 win->app_id = id;
178 win->app_id_set = 1;
179 insert_win_hashtab(win);
182 return win;
185 static void set_win_configuration(WinData *win, FvwmPacketBody *body)
187 win->desknum = body->add_config_data.desk;
188 win->x = body->add_config_data.frame_x;
189 win->y = body->add_config_data.frame_y;
190 win->width = body->add_config_data.frame_width;
191 win->height = body->add_config_data.frame_height;
192 win->iconified = IS_ICONIFIED(&(body->add_config_data));
193 win->state = (win == fvwm_focus_win) ? FOCUS_CONTEXT : PLAIN_CONTEXT;
194 win->geometry_set = 1;
195 memcpy(&(win->flags), &(body->add_config_data.flags),
196 sizeof(win->flags));
198 int wb_x = body->add_config_data.border_width;
199 int wb_y = body->add_config_data.border_width;
200 int t_w = 2*wb_x;
201 int t_h = 2*wb_y;
203 if (HAS_TITLE_DIR(win, DIR_N))
205 wb_y += body->add_config_data.title_height;
206 t_h += body->add_config_data.title_height;
208 else if (HAS_TITLE_DIR(win, DIR_W))
210 wb_x += body->add_config_data.title_height;
211 t_w += body->add_config_data.title_height;
213 if (HAS_TITLE_DIR(win, DIR_S))
215 t_h += body->add_config_data.title_height;
217 if (HAS_TITLE_DIR(win, DIR_E))
219 t_w += body->add_config_data.title_height;
221 win->real_g.x = win->x + wb_x;
222 win->real_g.y = win->y + wb_y;
223 win->real_g.width = win->width - t_w;
224 win->real_g.height = win->height - t_h;
228 static void handle_config_info(unsigned long *body)
230 char *tline, *token, *rest;
231 int color;
232 extern void process_dynamic_config_line(char *line);
234 tline = (char*)&(body[3]);
235 token = PeekToken(tline, &rest);
236 if (StrEquals(token, "Colorset"))
238 color = LoadColorset(rest);
239 change_colorset(color);
241 else if (StrEquals(token, XINERAMA_CONFIG_STRING))
243 FScreenConfigureModule(rest);
245 else if (StrEquals(token, "IgnoreModifiers"))
247 sscanf(rest, "%d", &mods_unused);
249 else if (strncasecmp(tline, Module, ModuleLen) == 0)
251 process_dynamic_config_line(tline);
255 static void configure_window(FvwmPacketBody *body)
257 Ulong app_id = body->add_config_data.w;
258 WinData *win;
259 ConsoleDebug(FVWM, "configure_window: %ld\n", app_id);
261 win = id_to_win(app_id);
263 set_win_configuration(win, body);
265 check_win_complete(win);
266 check_in_window(win);
267 got_configure(win->manager);
270 static void focus_change(FvwmPacketBody *body)
272 Ulong app_id = body->minimal_data.app_id;
273 WinData *win = id_to_win(app_id);
275 ConsoleDebug(FVWM, "Focus Change\n");
276 ConsoleDebug(FVWM, "\tID: %ld\n", app_id);
278 if (fvwm_focus_win &&
279 fvwm_focus_win->button &&
280 fvwm_focus_win->manager->showonlyfocused)
281 delete_windows_button(fvwm_focus_win);
283 if (fvwm_focus_win && win != fvwm_focus_win)
285 del_win_state(fvwm_focus_win, FOCUS_CONTEXT);
286 if (fvwm_focus_win->manager &&
287 fvwm_focus_win->manager->focus_button)
289 fvwm_focus_win->manager->focus_button = NULL;
291 fvwm_focus_win = NULL;
294 if (win->complete &&
295 win->button &&
296 win->manager &&
297 win->manager->window_up &&
298 win->manager->followFocus)
300 win->manager->focus_button = win->button;
302 add_win_state(win, FOCUS_CONTEXT);
304 check_in_window(win);
306 globals.focus_win = win;
307 fvwm_focus_win = win;
308 ConsoleDebug(FVWM, "leaving focus_change\n");
311 static void res_name(FvwmPacketBody *body)
313 Ulong app_id = body->name_data.app_id;
314 Uchar *name = body->name_data.name.name;
315 WinData *win;
317 ConsoleDebug(FVWM, "In res_name\n");
319 win = id_to_win(app_id);
321 copy_string(&win->resname, (char *)name);
322 change_windows_manager(win);
324 ConsoleDebug(FVWM, "Exiting res_name\n");
327 static void class_name(FvwmPacketBody *body)
329 Ulong app_id = body->name_data.app_id;
330 Uchar *name = body->name_data.name.name;
331 WinData *win;
333 ConsoleDebug(FVWM, "In class_name\n");
335 win = id_to_win(app_id);
337 copy_string(&win->classname, (char *)name);
338 change_windows_manager(win);
340 ConsoleDebug(FVWM, "Exiting class_name\n");
343 static void icon_name(FvwmPacketBody *body)
345 WinData *win;
346 Ulong app_id;
347 Uchar *name = body->name_data.name.name;
349 ConsoleDebug(FVWM, "In icon_name\n");
351 app_id = body->name_data.app_id;
353 win = id_to_win(app_id);
355 if (win->iconname && !strcmp(win->iconname, (char *)name))
357 ConsoleDebug(
358 FVWM, "No icon change: %s %s\n", win->iconname, name);
359 return;
362 copy_string(&win->iconname, (char *)name);
363 ConsoleDebug(FVWM, "new icon name: %s\n", win->iconname);
365 ConsoleDebug(FVWM, "Exiting icon_name\n");
368 static void visible_icon_name(FvwmPacketBody *body)
370 WinData *win;
371 Ulong app_id;
372 Uchar *name = body->name_data.name.name;
374 ConsoleDebug(FVWM, "In visible_icon_name\n");
376 app_id = body->name_data.app_id;
378 win = id_to_win(app_id);
380 if (win->visible_icon_name &&
381 !strcmp(win->visible_icon_name, (char *)name))
383 ConsoleDebug(
384 FVWM, "No icon change: %s %s\n", win->iconname, name);
385 return;
388 copy_string(&win->visible_icon_name, (char *)name);
389 ConsoleDebug(
390 FVWM, "new visible icon name: %s\n", win->visible_icon_name);
391 if (change_windows_manager(win) == 0 && win->button &&
392 (win->manager->format_depend & ICON_NAME))
394 if (win->manager->sort)
396 resort_windows_button(win);
400 ConsoleDebug(FVWM, "Exiting icon_name\n");
403 static void window_name(FvwmPacketBody *body)
405 WinData *win;
406 Ulong app_id;
407 Uchar *name = body->name_data.name.name;
409 ConsoleDebug(FVWM, "In window_name\n");
411 app_id = body->name_data.app_id;
413 win = id_to_win(app_id);
415 /* This is necessary because bash seems to update the window title on
416 every keystroke regardless of whether anything changes */
417 if (win->titlename && !strcmp(win->titlename, (char *)name))
419 ConsoleDebug(
420 FVWM, "No name change: %s %s\n", win->titlename, name);
421 return;
424 copy_string(&win->titlename, (char *)name);
426 ConsoleDebug(FVWM, "Exiting window_name\n");
429 static void visible_name(FvwmPacketBody *body)
431 WinData *win;
432 Ulong app_id;
433 Uchar *name = body->name_data.name.name;
435 ConsoleDebug(FVWM, "In visible_name\n");
437 app_id = body->name_data.app_id;
439 win = id_to_win(app_id);
441 /* This is necessary because bash seems to update the window title on
442 every keystroke regardless of whether anything changes */
443 if (win->visible_name && !strcmp(win->visible_name, (char *)name))
445 ConsoleDebug(
446 FVWM, "No visible name change: %s %s\n",
447 win->visible_name, name);
448 return;
451 copy_string(&win->visible_name, (char *)name);
452 if (change_windows_manager(win) == 0 && win->button &&
453 (win->manager->format_depend & TITLE_NAME))
455 if (win->manager->sort)
457 resort_windows_button(win);
460 ConsoleDebug(FVWM, "Exiting visible_name\n");
464 static void new_window(FvwmPacketBody *body)
466 WinData *win;
468 win = id_to_win(body->add_config_data.w);
469 memcpy(&(win->flags), &(body->add_config_data.flags), sizeof(win->flags));
470 set_win_configuration(win, body);
471 got_configure(win->manager);
472 check_win_complete(win);
473 check_in_window(win);
474 /* FIXME: not perfect, the manager is not know yet */
475 tips_cancel(win->manager);
478 static void destroy_window(FvwmPacketBody *body)
480 WinData *win;
481 Ulong app_id;
483 app_id = body->minimal_data.app_id;
484 win = id_to_win(app_id);
485 if (win->manager)
487 tips_cancel(win->manager);
489 if (win == globals.focus_win)
491 globals.focus_win = NULL;
493 delete_win_hashtab(win);
494 if (win->button)
496 ConsoleDebug(FVWM, "destroy_window: deleting windows_button\n");
497 delete_windows_button(win);
499 if (win == fvwm_focus_win)
501 fvwm_focus_win = NULL;
503 free_windata(win);
506 static void mini_icon(FvwmPacketBody *body)
508 Ulong app_id = body->mini_icon_data.app_id;
509 WinData *win;
511 if (!FMiniIconsSupported)
513 return;
515 win = id_to_win(app_id);
516 set_win_picture(
517 win, body->mini_icon_data.picture, body->mini_icon_data.mask,
518 body->mini_icon_data.alpha, body->mini_icon_data.depth,
519 body->mini_icon_data.width, body->mini_icon_data.height);
522 ConsoleDebug(
523 FVWM, "mini_icon: 0x%lx 0x%lx %dx%dx%d\n",
524 (unsigned long) win->pic.picture, (unsigned long) win->pic.mask,
525 win->pic.width, win->pic.height, win->pic.depth);
528 static void icon_location(FvwmPacketBody *body)
530 Ulong app_id = body->minimal_data.app_id;
531 WinData *win;
533 win = id_to_win(app_id);
534 if (win == NULL)
536 return;
538 win->icon_g.x = body->icon_data.xpos;
539 win->icon_g.y = body->icon_data.ypos;
540 win->icon_g.width = body->icon_data.icon_width;
541 if (win->icon_g.width <= 0)
543 win->icon_g.width = 1;
545 win->icon_g.height = body->icon_data.icon_height;
546 if (win->icon_g.height <= 0)
548 win->icon_g.height = 1;
550 check_in_window(win);
553 static void iconify(FvwmPacketBody *body, int dir)
555 Ulong app_id = body->minimal_data.app_id;
556 WinData *win;
558 win = id_to_win(app_id);
559 set_win_iconified(win, dir);
560 icon_location(body);
561 check_win_complete(win);
562 check_in_window(win);
565 static void window_shade(FvwmPacketBody *body, int do_shade)
567 Window w;
568 WinManager *man;
570 w = (Window)(body->minimal_data.app_id);
571 man = find_windows_manager(w);
572 if (man == NULL)
574 return;
576 if (do_shade)
578 man->flags.needs_resize_after_unshade = 0;
579 man->flags.is_shaded = 1;
581 else
583 man->flags.is_shaded = 0;
584 if (man->flags.needs_resize_after_unshade)
586 draw_manager(man);
587 man->flags.needs_resize_after_unshade = 0;
591 return;
594 /* only used by remanage_winlist */
596 static void update_win_in_hashtab(void *arg)
598 WinData *p = (WinData *)arg;
599 check_in_window(p);
602 void remanage_winlist(void)
604 walk_hashtab(update_win_in_hashtab);
605 draw_managers();
608 static void new_desk(FvwmPacketBody *body)
610 globals.desknum = body->new_desk_data.desknum;
611 remanage_winlist();
614 static void sendtomodule(FvwmPacketBody *body)
616 extern void execute_function(char *);
617 Uchar *string = body->name_data.name.name;
619 ConsoleDebug(FVWM, "Got string: %s\n", string);
621 execute_function((char *)string);
624 static void property_change(FvwmPacketBody *body)
626 WinManager *man = NULL;
627 int j;
629 if (body->property_data.id != 0)
631 if (!(man = find_windows_manager(body->property_data.id)))
632 return;
635 if (body->property_data.arg == MX_PROPERTY_CHANGE_BACKGROUND)
637 if (man != NULL &&
638 CSET_IS_TRANSPARENT_PR(man->colorsets[DEFAULT]))
640 recreate_background(man, DEFAULT);
641 force_manager_redraw(man);
643 if (man != NULL)
645 return;
647 for (j = 0; j < globals.num_managers; j++)
649 man = &globals.managers[j];
650 if (CSET_IS_TRANSPARENT_PR(man->colorsets[DEFAULT]))
652 recreate_background(man, DEFAULT);
653 force_manager_redraw(man);
657 else if (body->property_data.arg == MX_PROPERTY_CHANGE_SWALLOW &&
658 man != NULL)
660 man->swallowed = body->property_data.toggle;
661 if (man->swallowed && body->property_data.str)
663 unsigned long u;
665 if (sscanf((char *)body->property_data.str, "%lu",
666 &u) == 1)
668 man->swallower_win = (Window)u;
670 else
672 man->swallower_win = 0;
678 static void ProcessMessage(Ulong type, FvwmPacketBody *body)
680 int i;
682 ConsoleDebug(FVWM, "fvwm message type: %ld\n", type);
684 switch(type)
686 case M_CONFIG_INFO:
687 ConsoleDebug(FVWM, "DEBUG::M_CONFIG_INFO\n");
688 handle_config_info((unsigned long*)body);
689 break;
691 case M_CONFIGURE_WINDOW:
692 ConsoleDebug(FVWM, "DEBUG::M_CONFIGURE_WINDOW\n");
693 configure_window(body);
694 break;
696 case M_FOCUS_CHANGE:
697 ConsoleDebug(FVWM, "DEBUG::M_FOCUS_CHANGE\n");
698 focus_change(body);
699 break;
701 case M_RES_NAME:
702 ConsoleDebug(FVWM, "DEBUG::M_RES_NAME\n");
703 res_name(body);
704 break;
706 case M_RES_CLASS:
707 ConsoleDebug(FVWM, "DEBUG::M_RES_CLASS\n");
708 class_name(body);
709 break;
711 case M_MAP:
712 ConsoleDebug(FVWM, "DEBUG::M_MAP\n");
713 break;
715 case M_ADD_WINDOW:
716 ConsoleDebug(FVWM, "DEBUG::M_ADD_WINDOW\n");
717 new_window(body);
718 break;
720 case M_DESTROY_WINDOW:
721 ConsoleDebug(FVWM, "DEBUG::M_DESTROY_WINDOW\n");
722 destroy_window(body);
723 break;
725 case M_MINI_ICON:
726 ConsoleDebug(FVWM, "DEBUG::M_MINI_ICON\n");
727 mini_icon(body);
728 break;
730 case M_WINDOW_NAME:
731 ConsoleDebug(FVWM, "DEBUG::M_WINDOW_NAME\n");
732 window_name(body);
733 break;
735 case M_VISIBLE_NAME:
736 ConsoleDebug(FVWM, "DEBUG::M_VISIBLE_NAME\n");
737 visible_name(body);
738 break;
740 case M_ICON_NAME:
741 ConsoleDebug(FVWM, "DEBUG::M_ICON_NAME\n");
742 icon_name(body);
743 break;
745 case MX_VISIBLE_ICON_NAME:
746 ConsoleDebug(FVWM, "DEBUG::MX_VISIBLE_ICON_NAME\n");
747 visible_icon_name(body);
748 break;
750 case M_DEICONIFY:
751 ConsoleDebug(FVWM, "DEBUG::M_DEICONIFY\n");
752 iconify(body, 0);
753 SendUnlockNotification(fvwm_fd);
754 break;
756 case M_ICONIFY:
757 ConsoleDebug(FVWM, "DEBUG::M_ICONIFY\n");
758 iconify(body, 1);
759 SendUnlockNotification(fvwm_fd);
760 break;
762 case M_ICON_LOCATION:
763 icon_location(body);
764 break;
766 case M_END_WINDOWLIST:
767 ConsoleDebug(FVWM, "DEBUG::M_END_WINDOWLIST\n");
768 ConsoleDebug(
769 FVWM, "+++++ End window list +++++\n");
770 if (globals.focus_win && globals.focus_win->button)
772 globals.focus_win->manager->focus_button =
773 globals.focus_win->button;
775 globals.got_window_list = 1;
776 for (i = 0; i < globals.num_managers; i++)
778 create_manager_window(i);
780 break;
782 case M_NEW_DESK:
783 ConsoleDebug(FVWM, "DEBUG::M_NEW_DESK\n");
784 new_desk(body);
785 break;
787 case M_NEW_PAGE:
788 ConsoleDebug(FVWM, "DEBUG::M_NEW_PAGE\n");
789 if (globals.x == body->new_page_data.x &&
790 globals.y == body->new_page_data.y &&
791 globals.desknum == body->new_page_data.desknum)
793 ConsoleDebug(FVWM, "Useless NEW_PAGE received\n");
794 break;
796 globals.x = body->new_page_data.x;
797 globals.y = body->new_page_data.y;
798 globals.desknum = body->new_page_data.desknum;
799 if (fvwm_focus_win && fvwm_focus_win->manager &&
800 fvwm_focus_win->manager->followFocus)
802 /* need to set the focus on a page change */
803 add_win_state(fvwm_focus_win, FOCUS_CONTEXT);
805 for (i = 0; i < globals.num_managers; i++)
807 set_draw_mode(&globals.managers[i], 0);
809 break;
811 case M_STRING:
812 ConsoleDebug(FVWM, "DEBUG::M_STRING\n");
813 sendtomodule(body);
814 break;
816 case MX_PROPERTY_CHANGE:
817 ConsoleDebug(FVWM, "DEBUG::MX_PROPERTY_CHANGE\n");
818 property_change(body);
819 break;
821 case M_WINDOWSHADE:
822 window_shade(body, 1);
823 break;
825 case M_DEWINDOWSHADE:
826 window_shade(body, 0);
827 break;
829 default:
830 break;
833 check_managers_consistency();
835 for (i = 0; i < globals.num_managers; i++)
837 if (drawing(&globals.managers[i]))
839 draw_manager(&globals.managers[i]);
843 check_managers_consistency();
846 void ReadFvwmPipe(void)
848 FvwmPacket* packet;
850 PrintMemuse();
851 ConsoleDebug(FVWM, "DEBUG: entering ReadFvwmPipe\n");
853 if ((packet = ReadFvwmPacket(fvwm_fd[1])) == NULL)
855 exit(0);
857 else
859 ProcessMessage(packet->type, (FvwmPacketBody *)packet->body);
862 ConsoleDebug(FVWM, "DEBUG: leaving ReadFvwmPipe\n");